我有以下简单的代码连接到SSL网页

NSMutableURLRequest *urlRequest=[NSMutableURLRequest requestWithURL:url];
[ NSURLConnection sendSynchronousRequest: urlRequest returningResponse: nil error: &error ];

除非它给出一个错误,如果证书是自签名的一个错误域=NSURLErrorDomain Code=-1202 UserInfo=0xd29930“不受信任的服务器证书”。有没有一种方法来设置它接受连接(就像在浏览器中你可以按accept)或一种方法来绕过它?


当前回答

由Nathan de Vries发布的category工作区将通过AppStore私有API检查,并且在你无法控制NSUrlConnection对象的情况下很有用。 一个例子是NSXMLParser,它将打开你提供的URL,但不公开NSURLRequest或NSURLConnection。

在iOS 4中,解决方法似乎仍然有效,但仅在设备上,模拟器不再调用allowsAnyHTTPSCertificateForHost:方法。

其他回答

你必须使用NSURLConnectionDelegate来允许HTTPS连接iOS8有新的回调。

弃用:

connection:canAuthenticateAgainstProtectionSpace:
connection:didCancelAuthenticationChallenge:
connection:didReceiveAuthenticationChallenge:

相反,你需要声明:

connectionShouldUseCredentialStorage:发送以确定URL加载器是否应该使用凭据存储来验证连接。 connection:willSendRequestForAuthenticationChallenge: -告诉委托连接将发送一个身份验证挑战请求。

使用willSendRequestForAuthenticationChallenge,你可以像使用已弃用的方法一样使用challenge,例如:

// Trusting and not trusting connection to host: Self-signed certificate
[challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge];
[challenge.sender continueWithoutCredentialForAuthenticationChallenge:challenge];

NSURLRequest有一个叫做setAllowsAnyHTTPSCertificate:forHost:的私有方法,它会做你想做的事情。你可以通过一个类别在NSURLRequest上定义allowsAnyHTTPSCertificateForHost:方法,并设置它为你想要覆盖的主机返回YES。

这不是我的功劳,但我发现这个真的很适合我的需要。shouldAllowSelfSignedCert是我的BOOL变量。只需添加到你的NSURLConnection委托,你应该是rockin快速绕过每个连接的基础上。

- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)space {
     if([[space authenticationMethod] isEqualToString:NSURLAuthenticationMethodServerTrust]) {
          if(shouldAllowSelfSignedCert) {
               return YES; // Self-signed cert will be accepted
          } else {
               return NO;  // Self-signed cert will be rejected
          }
          // Note: it doesn't seem to matter what you return for a proper SSL cert
          //       only self-signed certs
     }
     // If no other authentication is required, return NO for everything else
     // Otherwise maybe YES for NSURLAuthenticationMethodDefault and etc.
     return NO;
}

与AFNetworking我已经成功地消费https webservice与以下代码,

NSString *aStrServerUrl = WS_URL;

// Initialize AFHTTPRequestOperationManager...
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.requestSerializer = [AFJSONRequestSerializer serializer];
manager.responseSerializer = [AFJSONResponseSerializer serializer];

[manager.requestSerializer setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
manager.securityPolicy.allowInvalidCertificates = YES; 
[manager POST:aStrServerUrl parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject)
{
    successBlock(operation, responseObject);

} failure:^(AFHTTPRequestOperation *operation, NSError *error)
{
    errorBlock(operation, error);
}];

理想情况下,iOS应用程序需要接受不受信任的证书时,应该只有两种情况。

场景A:您连接到使用自签名证书的测试环境。

场景B:您正在代理HTTPS流量使用MITM代理,如Burp Suite, Fiddler, OWASP ZAP等。代理将返回一个由自签名CA签名的证书,以便代理能够捕获HTTPS流量。

出于显而易见的原因,生产主机绝不应使用不受信任的证书。

如果你需要让iOS模拟器接受一个不受信任的证书用于测试目的,强烈建议你不要为了禁用NSURLConnection api提供的内置证书验证而更改应用程序逻辑。如果应用程序在没有删除此逻辑的情况下发布给公众,它将容易受到中间人攻击。

出于测试目的而接受不受信任证书的推荐方法是将签署证书的证书颁发机构(CA)证书导入您的iOS模拟器或iOS设备。我写了一篇快速的博客文章来演示如何在iOS模拟器中做到这一点:

使用ios模拟器接受不受信任的证书