2012-03-02 64 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,但它實際上解決了我的問題。

相關問題