2011-04-15 90 views
0

我正在嘗試連接到需要客戶端證書的服務器。 因此瀏覽到此服務器時發生的正常事件流是Web瀏覽器(包括Safari和Chrome)提示用戶選擇證書並重試操作。如何使用Cocoa中的WebView連接客戶端證書?

那麼我該如何在Cocoa項目的嵌入式WebView中完成這項工作呢? 我迄今識別爲誤差在didFailProvisionalLoadWithError方法提出:

- (void)webView:(WebView *)sender didFailProvisionalLoadWithError:(NSError *)error forFrame:(WebFrame *)frame { 
    NSLog(@"webView:didFailProvisionalLoadWithError:forFrame:"); 
    NSLog(@" error = %@", error); 
} 

錯誤確實是error = Error Domain=NSURLErrorDomain Code=-1206 UserInfo=0x1006a8030 "The server 「myserver.xxx」 requires a client certificate.
但我怎麼能顯示一個對話框,讓用戶可以選擇從鑰匙串的證書?

回答

3

問題解決。

WebView組件的(已知)問題是導致問題的原因。 與Apple打開了一個DTS支持票,並得到了解決方法。

編輯: 下面是DTS的解決方法(我不知道這是否仍然有效,因爲它是3年前):

馬格努斯好了,我有機會看看這個我知道 會怎麼樣。在我們開始討論WebView之前,我需要爲您提供高達 速度的NSURLConnection所使用的委託方法,這是用於實際加載數據的網絡的底層API的 。 NSURLConnection開始支持單一身份驗證 代理回調, - 連接:didReceiveAuthenticationChallenge :,到 它通過了當時支持的各種身份驗證質詢( )(用戶名/密碼樣式質詢)。在Mac OS X 10.6(與iOS 3.0)NSURLConnection的得到增強,支持兩種 另外類型的驗證挑戰TLS連接:○ 客戶身份挑戰 (NSURLAuthenticationMethodClientCertificate),給予委託 機會選擇一個客戶端身份給出TLS連接Ø 服務器信任挑戰(NSURLAuthenticationMethodServerTrust),給予 委託有機會重寫服務器信任評價 對於給定的TLS連接出於兼容性的原因,是不是 可能通過在所有 情況下對這些挑戰的代表,所以NSURLConnection引入了一個新的代理回調, -conne ction:canAuthenticateAgainstProtectionSpace:允許代表選擇這些挑戰。 * * *現在,讓我們回到您的應用程序。正如我所提到的,WebView使用 NSURLConnection,並且對於每個連接,充當連接 委託。它攔截認證挑戰,並將其傳遞給其資源加載委託人 。這適用於舊學校 認證挑戰,因爲WebView在沒有 的情況下不需要做任何特殊的事情;但是它對於TLS連接 認證挑戰失敗,因爲代理必須選擇那些 挑戰。您真正需要的是「canAuthenticateAgainstProtectionSpace」身份驗證挑戰的WebView版本 。嗯,事實證明,這實際上是實施。在通過開源的WebView查找 時,我發現有一個私人的 委託回調, -webView:resource:canAuthenticateAgainstProtectionSpace:forDataSource:, ,這正是你想要的。 http://www.opensource.apple.com/source/WebKit/WebKit-7533.20.25/mac/WebView/WebResourceLoadDelegatePrivate.h 如果您實施該方法,則可以選擇加入身份驗證質詢客戶端身份驗證,並基於該質詢向用戶提供允許用戶選擇身份的接口 。我在您的測試應用中對原型 進行了原型設計,它非常有魅力。下面是我用來 獲取客戶端的身份挑戰代碼: - (BOOL)webView的:(的WebView *)發件人資源:(ID)標識canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace forDataSource:(WebDataSource *)數據源{ 的NSLog( @「%@」,[protectionSpace authenticationMethod]); return [[protectionSpace authenticationMethod] isEqual:NSURLAuthenticationMethodClientCertificate]; }以下是我用來響應它的代碼: - (void)webView:(WebView *)發件人資源:(id)標識符didReceiveAuthenticationChallenge :(NSURLAuthenticationChallenge *)來自DataSource的挑戰:(WebDataSource *)dataSource { NSLog @ 「didReceiveAuthenticationChallenge」); NSString * authenticationMethod = [[challenge protectionSpace] authenticationMethod]; NSLog(@「authenticationMethod =%@」,authenticationMethod);

[[challenge sender] continueWithoutCredentialForAuthenticationChallenge:challenge]; } 

很顯然,在一個真正的應用程序你需要顯示一些UI,然後,一旦 用戶選擇客戶端的身份,爲它創建 (+憑證[NSURLCredential credentialWithIdentity:證書:持久性:] ) ,然後將該憑證應用於chalenge (-useCredential:forAuthenticationChallenge :)。 * * *那麼你從哪裏出發?不管你做了什麼,你應該 文件對WebView的錯誤獲取 -webView:資源:canAuthenticateAgainstProtectionSpace:forDataSource:委託回調發布在公共標題。這是一個顯而易見的,最令人討厭,最遺漏的。 http://developer.apple.com/bugreporter/ 一旦你提交了一個bug,請給我發送錯誤號,以便我可以 將它與這個事件聯繫起來。除此之外,未來的發展方向不會明朗。如果你正在創建一個非Mac App Store應用程序,那麼我的建議 應該是你實現了 'canAuthenticateAgainstProtectionSpace'委託回調,因爲我上面顯示了 並繼續你的生活。 OTOH,如果您正在創建一個 Mac App Store應用程序,其中嚴禁使用私有API(包括代理 回調),則生活會變得更加棘手。在這種情況下,讓我知道 ,我們可以討論你的選擇。分享和享受

+0

呃..謹慎說出問題本身,以及解決方法是...? – 2015-11-29 10:35:02

+1

@ZsoltSzatmari完成 – 2015-11-29 23:41:18

+0

很酷,感謝您的發佈! – 2015-11-30 12:56:42

1

設置WebResourceLoadDelegate並實現與驗證挑戰相關的委託方法。當收到驗證質詢時,系統會提示您,在此時您可以提供要使用的證書。

ETA:這裏是你如何創建從存儲在clientSide.p12證書的NSURLCredential

NSString *thePath = [[NSBundle mainBundle] 
     pathForResource:@"clientside" ofType:@"p12"]; 
NSData *PKCS12Data = [[NSData alloc] initWithContentsOfFile:thePath]; 
CFDataRef inPKCS12Data = (CFDataRef)PKCS12Data;  
SecIdentityRef identity; 
SecTrustRef trust; 
extractIdentityAndTrust(inPKCS12Data, &identity, &trust); 

SecCertificateRef certificate = NULL; 
SecIdentityCopyCertificate (identity, &certificate); 

const void *certs[] = {certificate}; 
CFArrayRef certArray = CFArrayCreate(kCFAllocatorDefault, certs, 1, NULL); 

NSURLCredential *credential = [NSURLCredential 
     credentialWithIdentity:identity 
     certificates:(NSArray*)certArray 
     persistence:NSURLCredentialPersistencePermanent]; 

這來自another question。您可能還會發現this question有幫助。我通過谷歌搜索發現這些「nsurlcredential證書」。

+0

謝謝,你能指點我一個樣品或提供一些(僞)代碼? – 2011-04-21 15:52:09

+0

示例:[TwitterStreamViewController](https://github.com/danielctull/json-framework/blob/1e4278a957c4df7ecddf412c70db38b98a5ed9d2/Examples/TwitterStream/Classes/TwitterStreamViewController.m#L50)另一種方法可能是在發出請求之前設置憑證。這與[AppController + WebResourceLoadDelegate.m]中的Cappucino NativeHost的HTTP-Auth一起使用(https://github.com/280north/cappuccino/blob/master/Tools/NativeHost/AppController%2BWebResourceLoadDelegate.m)。 – 2011-04-21 19:20:18

+0

但是,這些示例正在使用basich auth和username/pwd。我如何從鑰匙串中選擇證書並傳遞請求? – 2011-04-23 08:01:37