通过SSL请求Web服务

我正在努力使用https请求Web服务。 我收到这样的错误:

An error occured : The certificate for this server is invalid. You might be connecting to a server that is pretending to be “SERVER_ADDRESS” which could put your confidential information at risk. 

我没有使用NSUrlConnectionDelegate。 这是我的方法:

 - (void)sendRequestWithUrl:(NSURL*)url block:(void (^)(NSDictionary *dict, NSError *error)) block{ NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; [request setHTTPMethod:@"POST"]; [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]; NSError* err = nil; NSHTTPURLResponse* rsp = nil; // Perform the request synchronously on this thread NSData *rspData = [NSURLConnection sendSynchronousRequest:request returningResponse:&rsp error:&err]; if (rspData && err == nil) { NSDictionary *result = [NSJSONSerialization JSONObjectWithData:rspData options:NSJSONReadingMutableLeaves error:&err]; if(result) { block(result, err); } else { block(nil, err); } }else{ DLog(@"Requesting URL: %@ An error occured : %@",url,[err localizedDescription]); block(nil, err); } } 

我怎么能解决这个问题?

你应该把下面的委托方法添加到你的通信类中。

 - (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge { if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) { if ([YOUR_HOST isEqualToString:challenge.protectionSpace.host]) { [challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge]; } } [challenge.sender continueWithoutCredentialForAuthenticationChallenge:challenge]; } - (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace { return [protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]; } 

苹果有一个很好的技术说明:

“技术说明TN2232:HTTPS服务器信任评估”

https://developer.apple.com/library/ios/#technotes/tn2232/_index.html

那么我的解决scheme是创build类AsyncURLConnection这个代码我发现在http://stackoverflow.com某处但现在找不到它。 所以我会给代码:

AsyncURLConnection

。H

 #import <Foundation/Foundation.h> typedef void (^completeBlock_t)(NSData *data); typedef void (^errorBlock_t)(NSError *error); @interface AsyncURLConnection : NSObject{ NSMutableData *data_; completeBlock_t completeBlock_; errorBlock_t errorBlock_; } + (id)request:(NSString *)requestUrl completeBlock:(completeBlock_t)completeBlock errorBlock:(errorBlock_t)errorBlock; - (id)initWithRequest:(NSString *)requestUrl completeBlock:(completeBlock_t)completeBlock errorBlock:(errorBlock_t)errorBlock; + (id)requestWithMutable:(NSMutableURLRequest *)request completeBlock:(completeBlock_t)completeBlock errorBlock:(errorBlock_t)errorBlock; - (id)initWithMutableRequest:(NSMutableURLRequest *)request completeBlock:(completeBlock_t)completeBlock errorBlock:(errorBlock_t)errorBlock; @end 

.M

 #import "AsyncURLConnection.h" @implementation AsyncURLConnection + (id)requestWithMutable:(NSMutableURLRequest *)request completeBlock:(completeBlock_t)completeBlock errorBlock:(errorBlock_t)errorBlock { return [[self alloc] initWithMutableRequest:request completeBlock:completeBlock errorBlock:errorBlock]; } + (id)request:(NSString*)requestUrl completeBlock:(completeBlock_t)completeBlock errorBlock:(errorBlock_t)errorBlock { return [[self alloc] initWithRequest:requestUrl completeBlock:completeBlock errorBlock:errorBlock]; } - (id)initWithRequest:(NSString *)requestUrl completeBlock:(completeBlock_t)completeBlock errorBlock:(errorBlock_t)errorBlock { if ((self=[super init])) { data_ = [[NSMutableData alloc] init]; completeBlock_ = [completeBlock copy]; errorBlock_ = [errorBlock copy]; NSURL *url = [NSURL URLWithString:requestUrl]; NSURLRequest *request = [NSURLRequest requestWithURL:url]; [NSURLConnection connectionWithRequest:request delegate:self]; } return self; } - (id)initWithMutableRequest:(NSMutableURLRequest *)request completeBlock:(completeBlock_t)completeBlock errorBlock:(errorBlock_t)errorBlock { if ((self=[super init])) { data_ = [[NSMutableData alloc] init]; completeBlock_ = [completeBlock copy]; errorBlock_ = [errorBlock copy]; [NSURLConnection connectionWithRequest:request delegate:self]; } return self; } - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { [data_ setLength:0]; } - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { [data_ appendData:data]; } - (void)connectionDidFinishLoading:(NSURLConnection *)connection { completeBlock_(data_); } - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { errorBlock_(error); } - (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge { if ([challenge previousFailureCount] == 0) { NSURLCredential *newCredential; newCredential=[NSURLCredential credentialWithUser:@"someUser" password:@"someUser" persistence:NSURLCredentialPersistenceForSession]; [[challenge sender] useCredential:newCredential forAuthenticationChallenge:challenge]; DLog(@"responded to authentication challenge"); }else{ DLog(@"previous authentication failure"); } } 

所以在一些控制器中可以使用这个类:

 + (void) downloadFileForURL:(NSURL *) url completionBlock:(void (^)(NSData *data, NSError *error)) block { NSString *requestURL = @"https://www.google.lt/restServer/Method"; [AsyncURLConnection request:requestURL completeBlock:^(NSData *data) { /* success! */ dispatch_queue_t downloadQueue = dispatch_queue_create("Download queue", NULL); dispatch_async(downloadQueue, ^{ /* process downloaded data in Concurrent Queue */ if (data != nil) { block(data, nil); }else{ block(nil,nil); } dispatch_async(dispatch_get_main_queue(), ^{ /* update UI on Main Thread */ }); }); } errorBlock:^(NSError *error) { /* error! */ block(nil,error); }]; } 

希望这个代码可以帮助一些人。

谢谢大家的回答。

这总是发生在自签证书上。 通过使用NSURLConnectionDelegate

 - (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace { if ([protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) { return YES; } } 

尝试这个委托方法解决了我的同样的问题。

 - (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace { return [protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]; } - (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge { [challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge]; [challenge.sender continueWithoutCredentialForAuthenticationChallenge:challenge]; }