2012-03-02 36 views
1

这是一个似乎遍布各地的问题,但到目前为止我还没有找到明确的答案。是否可以在iPhone应用程序中加载带有自签名安全证书的SSL加密网站?

我负责为我的公司编写iPhone应用程序。我的公司有一个带有自签名证书的SSL-encrypted网站。该网站使用频率非常高,我的雇主希望通过iPhone轻松访问该网站。我的应用程序的功能是提供一种存储用于访问网站的凭证的方法,当用户打开应用程序时,它会自动将存储的凭据发送到网站,并跳过登录对话框直接进入网站。

我已经设置我的应用程序使用UIWebView并为该网站加载请求。我已经设置了常用的身份验证方法,如:

- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace {...} 
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {...} 

当我的应用程序达到了代码,我告诉UIWebView加载NSURLRequest的一部分,它不会遇到我的任何身份验证方法。它直接跳到didFailLoadWithError,并且错误告诉我,我正在连接到可能只是冒充我的网站的网站,因为它具有自签名证书。

我该如何解决这个问题?我已经找到了一些涉及NSURLConnection方法的答案,但是这些方法在我遇到错误之前似乎没有被调用,并且被迫停止加载页面。我也发现了一些涉及覆盖“无证”方法的答案,但是当我尝试实现该解决方案时,我的web视图从未到达“didFailLoadWithError”或“didFinishLoad”,并且从不显示任何内容。

+0

我知道这不是回答你的问题,我讨厌它,当人们提出这样的建议,因为可能有很好的理由,你不能这样做......但是获得非自签名证书的努力和成本是否会降低?他们对像godaddy.com这样的人很便宜,或者免费与http://www.startssl.com/ – Rory 2013-02-16 22:39:13

+0

是的,另一种解决方案是获得签名证书。至于简单地解决我们的具体问题,这可能会更容易。如果我花的时间比我多,我可能会回到我的老板那里并且确切地推荐它。但确保iOS可以处理未签名的证书也很重要。如果不可能这样做,这将成为苹果API的一个主要缺陷,楼上的某个人需要得到通知。谢谢你的提示,但我不知道有一个地方让这些免费。 – Andrew 2013-02-18 19:14:55

回答

2

UIWebKit委托不会通过任何NSURLConnection委托方法转发到您的应用程序。解决这个问题的一种方法是使用NSURLConnection加载页面,然后使用-loadData:MIMEType:textEncodingName:baseURL:将其推入UIWebView。一旦你这样做了,你已经验证了第一页,它(只要你的网站没有链接),应该保持安全。那么,我们如何验证自签名证书?

我不得不在今年早些时候用OSX应用程序解决这个问题,一旦我弄清楚我在做什么,假设你有类似的设置,这很简单。我在这里提出的解决方案实际上验证了服务器证书(尽管在我的情况下我使用的是专用CA,因此我将CA证书添加到信任根,而不是服务器证书,它应该与此一样正常工作)。

您需要将NSURLAuthenticationMethodServerTrust的测试添加到-connection:canAuthenticateAgainstProtectionSpace:-connection:didReceiveAuthenticationChallenge:方法中,以便您可以请求关注并处理安全挑战。

希望这会有所帮助。

-(BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace 
{ 
    // ... implement any other authentication here, such as your client side certificates or user name/password 

    if ([[protectionSpace authenticationMethod] isEqualToString: NSURLAuthenticationMethodServerTrust]) 
     return YES; 
    return NO; 
} 

-(void)connection:(NSURLConnection *)aConnection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge 
{ 
    NSURLProtectionSpace *protectionSpace = challenge.protectionSpace; 

      // implement your client side auth here for NSURLAuthenticationMethodHTTPDigest or basic or your client-side cert 

    if ([[protectionSpace authenticationMethod] isEqualToString: NSURLAuthenticationMethodServerTrust]) { 
     // install our private certificates or CAs 
     NSString *myCAString = @"<string containing your CA cert>"; 

     SecCertificateRef certRef = SecCertificateCreateWithData (NULL, (CFDataRef)[NSData dataFromBase64String: myCAString]); 
     NSArray *anchorArray = [NSArray arrayWithObject: (NSObject*)certRef]; 
     SecTrustSetAnchorCertificates(challenge.protectionSpace.serverTrust, (CFArrayRef) anchorArray); 

     SecTrustResultType trustResultType; 
     OSStatus err=SecTrustEvaluate(challenge.protectionSpace.serverTrust, &trustResultType); 

     if ((!err) && (trustResultType == kSecTrustResultProceed || trustResultType == kSecTrustResultConfirm || trustResultType == kSecTrustResultUnspecified)) { 
      [challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge]; 
     } else { 
      CFArrayRef certChain=NULL; 
      CSSM_TP_APPLE_EVIDENCE_INFO *statusChain; 
      SecTrustGetResult(challenge.protectionSpace.serverTrust, &trustResultType, &certChain, &statusChain); 
      [challenge.sender cancelAuthenticationChallenge:challenge]; 
     } 

    } else { 
     // Cancel if we don't know what it is about... this is supposed to be secure 
     [challenge.sender cancelAuthenticationChallenge:challenge]; 
    } 
} 
+0

什么是CTURLTransaction?我已经实现了一个涉及NSURLConnection而不是CTURLTransaction的类似方法,它是我的webview在尝试连接到站点时从不调用的方法之一。 – Andrew 2012-03-06 20:01:14

+0

对不起。我已经修复了我的答案,即删除我们的语料库Shim类,这是CTURLTransaction。 – gaige 2012-03-06 21:09:41

+0

UIWebKit委托不会将任何NSURLConnection委托方法转发给您的应用程序。解决这个问题的一种方法是使用NSURLConnection加载页面,然后使用''-loadData:MIMEType:textEncodingName:baseURL:''将其推入UIWebView。一旦你这样做了,你已经验证了第一页,它(只要你的网站没有链接),应该保持安全。 – gaige 2012-03-06 22:52:01

1

我已经设法通过使用RestKit框架来做你想做的事,所以是的,我可以证实它可以完成。去看RestKit sources他们是怎么做的,或者只是使用RestKit。 This says how to use SSL with RestKit。在我的情况下,有一个问题 - 自签名证书必须包含特定的扩展名,否则我总是得到kSecTrustResultRecoverableTrustFailure。去看here,答案是投票-1,但它实际上解决了我的问题。

相关问题