關於使用UIWebView載入HTTPS站點出現NSURLErrorDomain code=-1202
最近在做push 資訊到facebook中。當使用UIWebview載入https的站點時webview總是會報NSURLErrorDomain code=-1202,導致網頁載入失敗。自己列印錯誤和網上搜索是因為證書失效,https使用超文字安全傳輸協議,即超文字傳輸協議(HTTP)和SSL/TLS的組合,用以提供加密通訊及對網路伺服器身份的鑑定。當我們的伺服器使用自我簽名證書時,而UIWebView不允許使用自簽名證書,所以導致載入失敗。我們可以使用NSURLConnection通過它的代理canAuthenticateAgainstProtectionSpace可以允許這種情況,從而通過它進行認證。
#import <UIKit/UIKit.h>
#import "MyObject.h"
@interface ViewController :UIViewController<UIWebViewDelegate,NSURLConnectionDelegate>
{
UIWebView *_web;
NSURLConnection *_urlConnection;
NSURLRequest *_request;
BOOL _authenticated;
}
@end
@interfaceViewController ()
@end
@implementation
@synthesize myobject;
- (void)viewDidLoad
{
[superviewDidLoad];
_web = [[UIWebViewalloc] initWithFrame:CGRectMake(0,0,768,1024)];
_web.delegate =self;
_web.autoresizingMask =UIViewAutoresizingFlexibleWidth |UIViewAutoresizingFlexibleHeight;
[self.viewaddSubview:_web];
NSURL* _loadingURL =[
//_loadingURL=[NSURLRequest setAllowsAnyHTTPSCertificate:YES forHost:[_loadingURL host]];
_request = [NSMutableURLRequestrequestWithURL:_loadingURL];
[_webloadRequest:_request];
// Do any additional setup after loading the view, typically from a nib.
// UIImageView *uimage=[[UIImageView alloc] initWithImage:[UIImage imageNamed:@"image27.png"]];
// [self.view addSubview:uimage];
// MyObject *object=[[MyObject alloc]init];
// MyObject *object1=[object retain];
//self.myobject=object;
//myobject = object;
//NSLog(@"******retainCount:%d",[myobject retainCount]);
//NSLog(@"******self.retainCount:%d",[self.myobject retainCount]);
//[object release];
}
- (void)didReceiveMemoryWarning
{
[superdidReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Webview delegate
// Note: This method is particularly important. As the server is using a self signed certificate,
// we cannot use just UIWebView - as it doesn't allow for using self-certs. Instead, we stop the
// request in this method below, create an NSURLConnection (which can allow self-certs via the delegate methods
// which UIWebView does not have), authenticate using NSURLConnection, then use another UIWebView to complete
// the loading and viewing of the page. See connection:didReceiveAuthenticationChallenge to see how this works.
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType;
{
NSLog(@"Did start loading: %@ auth:%d", [[requestURL]absoluteString],_authenticated);
if (!_authenticated) {
_authenticated =NO;
_urlConnection = [[NSURLConnectionalloc] initWithRequest:_requestdelegate:self];
[_urlConnectionstart];
returnNO;
}
returnYES;
}
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error {
// 102 == WebKitErrorFrameLoadInterruptedByPolicyChange
NSLog(@"***********error:%@,errorcode=%d,errormessage:%@",error.domain,error.code,error.description);
if (!([error.domainisEqualToString:@"WebKitErrorDomain"] && error.code ==102)) {
//[self dismissWithError:error animated:YES];
}
}
#pragma mark - NURLConnection delegate
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge;
{
NSLog(@"WebController Got auth challange via NSURLConnection");
if ([challengepreviousFailureCount] ==0)
{
_authenticated =YES;
NSURLCredential *credential = [NSURLCredentialcredentialForTrust:challenge.protectionSpace.serverTrust];
[challenge.senderuseCredential:credentialforAuthenticationChallenge:challenge];
} else
{
[[challenge sender]cancelAuthenticationChallenge:challenge];
}
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response;
{
NSLog(@"WebController received response via NSURLConnection");
// remake a webview call now that authentication has passed ok.
_authenticated =YES;
[_webloadRequest:_request];
// Cancel the URL connection otherwise we double up (webview + url connection, same url = no good!)
[_urlConnectioncancel];
}
// We use this method is to accept an untrusted site which unfortunately we need to do, as our PVM servers are self signed.
- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace
{
return [protectionSpace.authenticationMethodisEqualToString:NSURLAuthenticationMethodServerTrust];
}
@end