关于https 和 ssl 可以参照相关文章,这样方便理解为什么https要做特殊处理。
通常需要使用https请求的情况有两种:
1:向https域名请求数据,如登录
2:UIWebView加载https页面,如银行页面
第一种情况(向https域名请求数据):
1:通常可以用NSURLConection:
- (void)addTrustedHost:(NSString *)trustedHost { if (![_trustedHosts containsObject:trustedHost]) { [_trustedHosts addObject:trustedHost]; NSURL *payURL = [NSURL URLWithString:trustedHost]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:payURL cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:60.0]; [request setHTTPMethod :@"POST" ]; [request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"]; //use choose to trust the certificate and send asynchronous request NSURLConnection *theConncetion = [[NSURLConnection alloc] initWithRequest:request delegate:self]; if (theConncetion) { theData = [[NSMutableData alloc] initWithData:nil]; ITTDINFO(@"ok"); }else{ ITTDINFO(@"error"); } while(!finished) { [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]; } } } // 回调 #pragma mark - #pragma mark - NSURLConnection Delegate - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { // NSString *htmlStr = [[[NSString alloc] initWithData:theData encoding:NSUTF8StringEncoding] autorelease]; // [webView loadHTMLString:htmlStr baseURL:[response URL]]; [theData setLength:0]; finished = YES; } - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { [theData appendData:data]; // NSString *htmlStr = [[[NSString alloc] initWithData:theData encoding:NSUTF8StringEncoding] autorelease]; // [webView loadHTMLString:htmlStr baseURL:nil]; } - (void)connectionDidFinishLoading:(NSURLConnection *)connection { [connection release]; } -(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { [connection release]; } - (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace { return [protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]; } - (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge { if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) { [challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]forAuthenticationChallenge:challenge]; } [challenge.sender continueWithoutCredentialForAuthenticationChallenge:challenge]; }
回调里面最后面两个函数是关键,这里面的用例子是信赖所有需要验证的请求,也可以自己在里面判断哪些可以信赖,哪些是不能通过的。
2:ASIHttpRequest请求
- (void)doAsiRequest { NSDictionary *parameter = [NSDictionary dictionaryWithObjectsAndKeys: @"",@"", nil]; NSString *url = @"https://www.domain.com"; NSURL *nsURL = [NSURL URLWithString:url]; ASIFormDataRequest *formRequest = [[ASIFormDataRequest alloc] initWithURL:nsURL]; //Setup header [formRequest setTimeOutSeconds:30]; ITTRequestMethod method = ITTRequestMethodPost; if (ITTRequestMethodGet == method) { [formRequest setRequestMethod:@"GET"]; } else { [formRequest setRequestMethod:@"POST"]; //Post format ASIPostFormat postFormat = ASIURLEncodedPostFormat; //Add user parameters if (parameter || [parameter count]) { for (NSString *key in parameter) { [formRequest addPostValue:[parameter objectForKey:key] forKey:key]; } } formRequest.postFormat = postFormat; } formRequest.delegate = self; formRequest.defaultResponseEncoding = NSUTF8StringEncoding; formRequest.allowCompressedResponse = YES; formRequest.shouldCompressRequestBody = NO; formRequest.validatesSecureCertificate = NO; [formRequest setDidFinishSelector:@selector(requestFinished:)]; [formRequest startAsynchronous]; [formRequest release]; }
整观代码,其实起作用就是一句,就是方便
formRequest.validatesSecureCertificate = NO;
3:这种方法是需要暴露苹果私有API,所以不推荐,但是如果只是想自己写着玩玩,测试一下,还是可以用这种简单的方法的,话说就一个函数,苹果为什么不公 开…
@interface NSURLRequest (DummyInterface) + (BOOL)allowsAnyHTTPSCertificateForHost:(NSString*)host; + (void)setAllowsAnyHTTPSCertificate:(BOOL)allow forHost:(NSString*)host; @end //请求前设置好 [NSURLRequest setAllowsAnyHTTPSCertificate: YES forHost:[payURL host]];
第二种情况(UIWebView加载https页面):
有的时候,需要用UIWebView来加载一些https页面,在safari里是可以弹出是否继续的提示来手动处理,但是在iOS的webview里又没有这个功能,所以苹果又给我们制造了一个问题,前面第一种情况介绍了三种情况,实际把前面结合起来,我们就可以用webview来加载了,实际上就是多干一件事
- (void)doLoadHtmlStr:(NSDictionary *)dic { NSString *htmlStr = @""; // Replace by code below //[NSURLRequest setAllowsAnyHTTPSCertificate: YES forHost:[payURL host]]; // or [self addTrustedHost:[payParameterDic objectForKey:@"epayurl"]]; [webView loadHTMLString:htmlStr baseURL:nil]; } //回调 #pragma --WebViewDelegate-- - (BOOL)webView:(UIWebView *)webView1 shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType { self.urlString = [NSString stringWithFormat:@"%@", [request URL]]; //如果有多个https之间跳转,那么可以每一次判断一下,然后一个个加信赖 if ([[[request URL] scheme] isEqualToString:@"https"]) { [self addTrustedHost:self.urlString]; } return YES; } - (void)webViewDidStartLoad:(UIWebView *)webView { } - (void)webViewDidFinishLoad:(UIWebView *)webView; { NSString *absoluteString = [self.webView.request.URL absoluteString]; if (absoluteString) { NSRange foundRange = [absoluteString rangeOfString:@"/xxx/xxx"]; if(foundRange.location != NSNotFound) { [self doSomething]; } } } - (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error { NSLog(@"webview failed! Error %@ - %@ - %@", error, [error userInfo], [error localizedDescription]); [[ITTActivityIndicator currentIndicator] hide]; }