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

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

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


当前回答

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

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

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

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

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

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

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

其他回答

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

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

在iOS 9中,对于所有无效或自签名的证书,SSL连接将失败。这是iOS 9.0或更高版本、OS X 10.11及更高版本中新的应用程序传输安全特性的默认行为。

您可以在“信息”中覆盖此行为。通过在NSAppTransportSecurity字典中将NSAllowsArbitraryLoads设置为YES。但是,我建议仅为测试目的重写此设置。

有关信息,请参阅这里的应用程序传输技术说明。

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

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

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

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

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

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

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

您可以使用此代码

-(void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
     if ([[challenge protectionSpace] authenticationMethod] == NSURLAuthenticationMethodServerTrust)
     {
         [[challenge sender] useCredential:[NSURLCredential credentialForTrust:[[challenge protectionSpace] serverTrust]] forAuthenticationChallenge:challenge];
     }
}

使用-connection:willSendRequestForAuthenticationChallenge:代替这些已弃用的方法

弃用:

-(BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace  
-(void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge 
-(void)connection:(NSURLConnection *)connection didCancelAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge

这不是我的功劳,但我发现这个真的很适合我的需要。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;
}