通过SSL请求网络服务
问题描述:
我很努力地使用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);
}
}
我怎么能解决这个问题?
答
您应该将下面的委托方法添加到您的通信类。
- (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
答
这始终是自签名证书发生。通过使用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];
}
答
那么我的解决方案是创建AsyncURLConnection
类此代码,我发现某处在http://*.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);
}];
}
希望这个代码可以帮助一些人。
谢谢大家的回答。
对我来说,你遇到了自签证书的问题..正确吗? 我建议你改成一个库,如[AFNetworking](https://github.com/AFNetworking/AFNetworking/blob/master/README.md)或[MKNetworking](https://github.com/MugunthKumar/MKNetworkKit /blob/master/README.mdown),这使得这些问题更容易处理。检查:http://*.com/questions/13077753/need-to-view-website-with-a-self-signed-certificate-and-http-authentication – 2013-02-15 12:36:32
此外,可能重复:http:// *。 com/questions/933331 /如何使用nsurlconnection-to-connect-with-ssl-for-an-untrusted-cert – 2013-02-15 12:37:55
我不想使用其他库。另外在给定的其他问题解决方案 – Streetboy 2013-02-16 07:50:40