驗證挑戰(zhàn)和TLS鏈驗證 <- URL會話編程指南

NSURLRequest對象經(jīng)常遇到驗證挑戰(zhàn),或者從其他連接的服務(wù)器請求證書。當(dāng)請求遇到驗證挑戰(zhàn)的時候,NSURLSession類會通知它的委托,以便它們能夠相應(yīng)的執(zhí)行。

重要:URL加載系統(tǒng)的類一般不調(diào)用它們的委托來處理請求挑戰(zhàn),除非服務(wù)器的響應(yīng)包含WWW-Authenticate頭部。其他的驗證類型,例如代理驗證和TLS信任驗證,不需要此頭部。

決定如何響應(yīng)一個驗證挑戰(zhàn)

如果會話任務(wù)請求驗證,并且沒有有效的證書可用,作為請求URL的一部分或者共享的NSURLCredentialStorage,它會創(chuàng)建一個驗證挑戰(zhàn)。它首先發(fā)送URLSession:task:didReceiveChallenge:completionHandler: 到它的任務(wù)委托來處理該驗證挑戰(zhàn)。如果任務(wù)委托沒有響應(yīng)這個消息,該任務(wù)會發(fā)送URLSession:task:didReceiveChallenge:completionHandler:給它的會話委托來處理這個認(rèn)證挑戰(zhàn)。

為了繼續(xù)連接,委托由三個選項:

  • 提供驗證證書。
  • 嘗試無證書連接。
  • 取消驗證挑戰(zhàn)。

為了幫助確定正確的操作過程,傳遞給該方法的NSURLAuthenticationChallenge實(shí)例包含關(guān)于觸發(fā)該驗證挑戰(zhàn)的信息、對挑戰(zhàn)進(jìn)行的嘗試次數(shù)、任何之前嘗試的證書、請求證書的NSURLProtectionSpace、以及挑戰(zhàn)的發(fā)送者。

如果驗證挑戰(zhàn)之前已經(jīng)有驗證但驗證失?。ɡ?,如果用戶改變了密碼或服務(wù)器),你可以通過調(diào)用驗證挑戰(zhàn)中的hproposedCredential來獲取嘗試的證書。然后該委托把這些證書通過彈出對話框顯示給用戶。

調(diào)用驗證挑戰(zhàn)的previousFailureCount,返回之前驗證嘗試的總次數(shù),包括了不同驗證協(xié)議的嘗試。該委托可以抱這些信息提供給用戶,已確定之前提供的證書是否失敗,或者限制驗證嘗試次數(shù)。

響應(yīng)驗證挑戰(zhàn)

以下三種方法是對URLSession:didReceiveChallenge:completionHandler: 或 URLSession:task:didReceiveChallenge:completionHandler:委托方法的響應(yīng)。

提供證書

要想嘗試驗證,應(yīng)用程序應(yīng)該使用驗證信息創(chuàng)建NSURLCredential對象,該驗證信息應(yīng)該符合服務(wù)器的要求。你可以通過在提供驗證挑戰(zhàn)的保護(hù)空間中調(diào)用authenticationMethod確定服務(wù)器的驗證方法。NSURLCredential支持一些驗證方法:

  • HTTP基礎(chǔ)驗證(NSURLAuthenticationMethodHTTPBasic)需要用戶名和密碼。提示用戶提供必要的信息,并且使用credentialWithUser:password:persistence:創(chuàng)建NSURLCredential對象。
  • HTTP摘要驗證(NSURLAuthenticationMethodHTTPDigest),類似基礎(chǔ)驗證,需要用戶名和密碼。(該摘要是自動生成的。)提示用戶提供必要的信息,并使用credentialWithUser:password:persistence:創(chuàng)建NSURLCredential對象。
  • 客戶端證書驗證(NSURLAuthenticationMethodClientCertificate)要求系統(tǒng)身份和所有必要的證書通過服務(wù)器進(jìn)行身份驗證。使用credentialWithIdentity:certificates:persistence:創(chuàng)建NSURLCredential對象。
  • 服務(wù)器信任驗證(NSURLAuthenticationMethodServerTrust)需要由驗證挑戰(zhàn)的保護(hù)空間提供信任(trust)。使用credentialForTrust:創(chuàng)建NSURLCredential對象。

在你創(chuàng)建了NSURLCredential對象之后,使用提供的完成處理程序代碼塊把這個對象傳遞給驗證挑戰(zhàn)的發(fā)送者。

無證書連接

如果委托選擇不向驗證挑戰(zhàn)提供證書,它可以嘗試無驗證的繼續(xù)連接。把下面值之一傳遞給完成處理程序代碼塊:

  • NSURLSessionAuthChallengePerformDefaultHandling處理請求,就像委托不提供委托方法來處理挑戰(zhàn)一樣。
  • NSURLSessionAuthChallengeRejectProtectionSpace拒絕挑戰(zhàn)。根據(jù)服務(wù)器響應(yīng)允許的驗證類型,URL加載類或許調(diào)用這個委托方法不止一次,以獲取額外的保護(hù)空間。
取消連接

通過給提供的完成處理程序代碼塊傳遞NSURLSessionAuthChallengeCancelAuthenticationChallenge,委托也可以選擇取消驗證挑戰(zhàn)。

驗證樣例

代碼清單4-1 展示了,通過創(chuàng)建NSURLCredential實(shí)例響應(yīng)挑戰(zhàn)。該實(shí)例使用通過應(yīng)用程序的首選項提供的用戶名和密碼創(chuàng)建。如果該驗證之前失敗,它會取消認(rèn)證挑戰(zhàn)并通知用戶。

代碼清單 4-1 使用URLSession:didReceiveChallenge:completionHandler:委托方法的示例

- (void)URLSession:(NSURLSession *)session

didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge

  completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * __nullable credential))completionHandler

{

    if ([challenge previousFailureCount] == 0) {

        NSURLCredential *newCredential = [NSURLCredential credentialWithUser:[self preferencesName]

                                                                    password:[self preferencesPassword]

                                                                 persistence:NSURLCredentialPersistenceNone];

        completionHandler(NSURLSessionAuthChallengeUseCredential, newCredential);

    } else {

        // Inform the user that the user name and password are incorrect

        completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil);

    }

}
func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {

    guard challenge.previousFailureCount == 0 else {

        challenge.sender?.cancel(challenge)

        // Inform the user that the user name and password are incorrect

        completionHandler(.cancelAuthenticationChallenge, nil)

        return

    }

    

    let proposedCredential = URLCredential(user: self.preferencesName, password: self.preferencesPassword, persistence: .none)

    completionHandler(.useCredential, proposedCredential)

}

如果驗證挑戰(zhàn)沒有被會話或任務(wù)委托處理,且證書不可用或使用它們驗證失敗,continueWithoutCredentialForAuthenticationChallenge消息會通過底層的實(shí)現(xiàn)發(fā)送。

執(zhí)行自定義的TLS鏈驗證

在NSURL系列API中,TLS鏈驗證通過app驗證委托方法處理,而不是提供驗證用戶(或app)的證書給服務(wù)器。App會在TLS握手期間檢查服務(wù)器提供的證書,然后告訴URL加載系統(tǒng)是否應(yīng)該接受或拒絕這些證書。

如果你需要以非標(biāo)準(zhǔn)的方式執(zhí)行鏈驗證(例如,為測試接收一個特定的自簽名證書),app必須實(shí)現(xiàn)URLSession:didReceiveChallenge:completionHandler: 或 URLSession:task:didReceiveChallenge:completionHandler:委托方法。如果兩者都實(shí)現(xiàn),則會話級別的方法負(fù)責(zé)處理驗證。

在你的驗證處理委托方法中,你應(yīng)該檢查挑戰(zhàn)保護(hù)空間是否有NSURLAuthenticationMethodServerTrust的驗證類型,如果有,從保護(hù)空間獲取serverTrust信息。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 你可以用兩種方式使用NSURLSession API:系統(tǒng)提供的委托或自定義的委托。通常情況下,如果app由下面的...
    raingu24閱讀 474評論 0 2
  • NSURLSession及其相關(guān)的類提供了通過HTTP下載內(nèi)容的API。這個類提供了豐富的委托方法來支持驗證、以及...
    raingu24閱讀 782評論 0 0
  • 概述 NSURLSession類和其相關(guān)的類提供了下載內(nèi)容的API.此類提供了豐富的代理方法集合以支持驗證并且在應(yīng)...
    Mob_Developer閱讀 2,485評論 0 0
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,506評論 19 139
  • 《黃昏》 文/白傳英 我走向你的時候 天空已黎明 在你的霞光里 我快樂地前行 耳邊是十里春風(fēng) 里面包裹著我的...
    白清風(fēng)閱讀 129評論 0 0

友情鏈接更多精彩內(nèi)容