2013-02-15 183 views
8

我很努力地使用https請求網絡服務。我得到這種錯誤:通過SSL請求網絡服務

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); 
    } 
} 

我怎麼能解決這個問題?

+1

對我來說,你遇到了自簽證書的問題..正確嗎? 我建議你改成一個庫,如[AFNetworking](https://github.com/AFNetworking/AFNetworking/blob/master/README.md)或[MKNetworking](https://github.com/MugunthKumar/MKNetworkKit /blob/master/README.mdown),這使得這些問題更容易處理。檢查:http://stackoverflow.com/questions/13077753/need-to-view-website-with-a-self-signed-certificate-and-http-authentication – 2013-02-15 12:36:32

+1

此外,可能重複:http:// stackoverflow。 com/questions/933331 /如何使用nsurlconnection-to-connect-with-ssl-for-an-untrusted-cert – 2013-02-15 12:37:55

+1

我不想使用其他庫。另外在給定的其他問題解決方案 – Streetboy 2013-02-16 07:50:40

回答

1

您應該將下面的委託方法添加到您的通信類。

- (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]; 
} 
0

這始終是自簽名證書發生。通過使用NSURLConnectionDelegate

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

這段代碼如何調整到我的?我知道如何使用NSURLConnectionDelegate,但是如何使用塊 – Streetboy 2013-02-19 09:55:28

+0

做到這一點,爲什麼你不想使用NSURLConnectionDelegate?有什麼可以破壞你的代碼嗎? – 2013-02-19 10:12:12

+0

我想更新我當前的代碼,因爲在其他方面,我需要做很多改變,因爲現在一切都是按塊完成的。另外我喜歡用這種方法編寫代碼 – Streetboy 2013-02-19 11:11:06

0

嘗試使用這種委託方法解決了同樣的問題。

- (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]; 
} 
2

那麼我的解決方案是創建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); 
    }]; 
} 

希望這個代碼可以幫助一些人。

謝謝大家的回答。