URL加載系統(tǒng)之四:認(rèn)證與TLS鏈驗(yàn)證

一個(gè)NSURLRequest對(duì)象經(jīng)常會(huì)遇到認(rèn)證請(qǐng)求,或者需要從其所連接的服務(wù)端請(qǐng)求證書(shū)。當(dāng)需要認(rèn)證請(qǐng)求時(shí),NSURLConnection、NSURLSession和NSURLDownload類(lèi)會(huì)通知它們的代理對(duì)象,以便能正確地做處理。不過(guò)需要注意的是,URL加載系統(tǒng)只有在服務(wù)端響應(yīng)包含WWW-Authenticate頭時(shí)才會(huì)調(diào)用代理來(lái)處理認(rèn)證請(qǐng)求,而類(lèi)似于代理認(rèn)證和TLS信任驗(yàn)證這樣的認(rèn)證類(lèi)型則不需要這個(gè)頭。

確定如何響應(yīng)一個(gè)認(rèn)證請(qǐng)求

如果一個(gè)NSURLRequest對(duì)象需要認(rèn)證時(shí),則認(rèn)證請(qǐng)求方式取決于使用的對(duì)象的類(lèi)型:

如果請(qǐng)求是與NSURLSession對(duì)象關(guān)聯(lián),則所有認(rèn)證請(qǐng)求都會(huì)傳遞給代理,而不考慮認(rèn)證的類(lèi)型。

如果請(qǐng)求是與NSURLConnection或NSURLDownload對(duì)象,則對(duì)象的代理接收一個(gè)connection:canAuthenticateAgainstProtectionSpace: (或者 download:canAuthenticateAgainstProtectionSpace:) 消息。這允許代理對(duì)象在嘗試再次認(rèn)證前分析服務(wù)端的屬性,包括協(xié)議和認(rèn)證方法。如果我們的代理對(duì)象不準(zhǔn)備認(rèn)證服務(wù)端的受保護(hù)空間,則返回NO,且系統(tǒng)嘗試使用用戶(hù)的keychain的信息進(jìn)行認(rèn)證。

如果NSURLConnection或NSURLDownload的代理對(duì)象沒(méi)有實(shí)現(xiàn)connection:canAuthenticateAgainstProtectionSpace: (或者 download:canAuthenticateAgainstProtectionSpace:)方法,且保護(hù)空間使用客戶(hù)端證書(shū)認(rèn)證或服務(wù)端信任認(rèn)證,則系統(tǒng)假設(shè)我們返回NO。而對(duì)象其它所有類(lèi)型,系統(tǒng)都返回YES。

下一步,如果我們的代理對(duì)象同意處理認(rèn)證,但是沒(méi)有有效的證書(shū)(不管是作為請(qǐng)求URL的一部分或者在NSURLCredentialStorage中共享),則代理以收到以下消息:

URLSession:didReceiveChallenge:completionHandler:2. URLSession:task:didReceiveChallenge:completionHandler:3. connection:didReceiveAuthenticationChallenge:4. download:didReceiveAuthenticationChallenge:

為了讓連接能夠繼續(xù),則代理對(duì)象有三種選擇:

提供認(rèn)證證書(shū)

嘗試在沒(méi)有證書(shū)的情況下繼續(xù)

取消認(rèn)證查詢(xún)

為了確保操作的正確流程,傳遞給這些方法的NSURLAuthenticationChallenge實(shí)例會(huì)包含一些信息,包括是什么觸發(fā)了認(rèn)證查詢(xún)、查詢(xún)的嘗試次數(shù)、任何先前嘗試的證書(shū)、請(qǐng)求證書(shū)的NSURLProtectionSpace對(duì)象,及查詢(xún)的發(fā)送者。

如果認(rèn)證請(qǐng)求事先嘗試認(rèn)證且失敗了(如用戶(hù)在服務(wù)端修改了密碼),我們可以通過(guò)在認(rèn)證請(qǐng)求調(diào)用proposedCredential來(lái)獲取嘗試憑據(jù)。代理可以使用這些證書(shū)來(lái)填充一個(gè)顯示給用戶(hù)的話(huà)框。

調(diào)用認(rèn)證請(qǐng)求的previousFailureCount可以返回身份驗(yàn)證嘗試次數(shù),這些嘗試包括不同認(rèn)證協(xié)議的嘗試請(qǐng)求。代理可以將這些方法提供給用戶(hù),以確定先前提供的證書(shū)是否失敗,或限制最大認(rèn)證嘗試次數(shù)。

響應(yīng)認(rèn)證請(qǐng)求

前面說(shuō)過(guò)三種響應(yīng)我們響應(yīng)connection:didReceiveAuthenticationChallenge:代理方法的方式,我們將逐一介紹:

提供證書(shū)

為了進(jìn)行認(rèn)證,程序需要使用服務(wù)端期望的認(rèn)證信息創(chuàng)建一個(gè)NSURLCredential對(duì)象。我們可以調(diào)用authenticationMethod來(lái)確定服務(wù)端的認(rèn)證方法,這個(gè)認(rèn)證方法是在提供的認(rèn)證請(qǐng)求的保護(hù)空間中。NSURLCredential支持一些方法:

HTTP基本認(rèn)證(NSURLAuthenticationMethodHTTPBasic):需要用戶(hù)名和密碼。提示用戶(hù)輸入必要信息并使用credentialWithUser:password:persistence:方法創(chuàng)建一個(gè)NSURLCredential對(duì)象。

HTTP數(shù)字認(rèn)證(NSURLAuthenticationMethodHTTPDigest):類(lèi)似于基本認(rèn)證,需要用戶(hù)名和密碼。提示用戶(hù)輸入必要信息并使用credentialWithUser:password:persistence:方法創(chuàng)建一個(gè)NSURLCredential對(duì)象。

客戶(hù)端證書(shū)認(rèn)證(NSURLAuthenticationMethodClientCertificate): 需要系統(tǒng)標(biāo)識(shí)和所有服務(wù)端認(rèn)證所需要的證書(shū)。然后使用credentialWithIdentity:certificates:persistence:來(lái)創(chuàng)建一個(gè)NSURLCredential對(duì)象。

服務(wù)端信任認(rèn)證(NSURLAuthenticationMethodServerTrust)需要一個(gè)由認(rèn)證請(qǐng)求的保護(hù)空間提供的信任。使用credentialForTrust:來(lái)創(chuàng)建一個(gè)NSURLCredential對(duì)象。

在創(chuàng)建NSURLCredential對(duì)象后

對(duì)于NSURLSession,使用提供的完成處理block將該對(duì)象傳遞給認(rèn)證請(qǐng)求發(fā)送者

對(duì)于NSURLConnection和NSURLDownload,使用useCredential:forAuthenticationChallenge:方法將對(duì)象傳遞給認(rèn)證請(qǐng)求發(fā)送者。

嘗試在沒(méi)有證書(shū)的情況下繼續(xù)

如果代理選擇不提供證書(shū),可以嘗試?yán)^續(xù)操作:

對(duì)于NSURLSession,傳遞下面的值給完成處理block: NSURLSessionAuthChallengePerformDefaultHandling:處理請(qǐng)求。盡管代理沒(méi)有提供代理方法來(lái)處理認(rèn)證請(qǐng)求 NSURLSessionAuthChallengeRejectProtectionSpace:拒絕請(qǐng)求。依賴(lài)于服務(wù)端響應(yīng)允許的認(rèn)證類(lèi)型,URL加載類(lèi)可能多次調(diào)用這個(gè)代理方法。

對(duì)于NSURLConnection和NSURLDownload,在[challenge sender]中調(diào)用continueWithoutCredentialsForAuthenticationChallenge:。

依賴(lài)于協(xié)議的實(shí)現(xiàn),這種處理方法可能會(huì)導(dǎo)致連接失敗而以送connectionDidFailWithError:消息,或者返回可選的不需要認(rèn)證的URL內(nèi)容。

取消連接

代理可以選擇取消認(rèn)證請(qǐng)求

對(duì)于NSURLSession,傳遞NSURLSessionAuthChallengeCancelAuthenticationChallenge給完成處理block

對(duì)于NSURLConnection和NSURLDownload,在[challenge sender]中調(diào)用cancelAuthenticationChallenge:。代理接收connection:didCancelAuthenticationChallenge:消息,以提供用戶(hù)反饋的機(jī)會(huì)。

下面的代碼演示了使用用戶(hù)名和密碼創(chuàng)建NSURLCredential對(duì)象來(lái)響應(yīng)認(rèn)證請(qǐng)求

-(void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge

{

if ([challenge previousFailureCount] == 0)

{

NSURLCredential *newCredential;

newCredential = [NSURLCredential credentialWithUser:[self preferencesName] password:[self preferencesPassword] persistence:NSURLCredentialPersistenceNone];

[[challenge sender] useCredential:newCredential forAuthenticationChallenge:challenge];

}

else

{? ? ? ? ? [[challenge sender] cancelAuthenticationChallenge:challenge];? ? ? ? ? // inform the user that the user name and password? ? ? ? ? // in the preferences are incorrect? ? ? ? [self showPreferencesCredentialsAreIncorrectPanel:self];? ? ? ? }

}

如果代理沒(méi)有實(shí)現(xiàn)connection:didReceiveAuthenticationChallenge:,而請(qǐng)求需要認(rèn)證,則有效的證書(shū)必須位于URL證書(shū)存儲(chǔ)中或作為請(qǐng)求URL的一部分。如果證書(shū)無(wú)效或者認(rèn)證失敗,則底層實(shí)現(xiàn)會(huì)發(fā)送一個(gè)continueWithoutCredentialForAuthenticationChallenge:消息。

執(zhí)行自定義TLS鏈驗(yàn)證

在NSURL系統(tǒng)的AIP中,TLS鏈驗(yàn)證由應(yīng)用的認(rèn)證代理方法來(lái)處理,但它不是提供證書(shū)給服務(wù)端以驗(yàn)證用戶(hù),而是在TLS握手的過(guò)程中校驗(yàn)服務(wù)端提供的證書(shū),然后再告訴URL加載系統(tǒng)是否應(yīng)該接受還是拒絕這些證書(shū)。

如果需要以非標(biāo)準(zhǔn)的方法(如接收一個(gè)指定的自標(biāo)識(shí)的證書(shū)用于測(cè)試)來(lái)執(zhí)行鏈驗(yàn)證,則應(yīng)用必須如下處理:

對(duì)于NSURLSession,實(shí)現(xiàn)URLSession:didReceiveChallenge:completionHandler:和URLSession:task:didReceiveChallenge:completionHandler:代理方法。如果實(shí)現(xiàn)了兩者,由會(huì)話(huà)級(jí)別的方法負(fù)責(zé)處理認(rèn)證。

對(duì)于NSURLConnection和NSURLDownload,實(shí)現(xiàn)connection:canAuthenticateAgainstProtectionSpace:和download:canAuthenticateAgainstProtectionSpace:方法,如果保護(hù)空間有一個(gè)NSURLAuthenticationMethodServerTrust類(lèi)型的認(rèn)證,則返回YES。然后,實(shí)現(xiàn)connection:didReceiveAuthenticationChallenge:或download:didReceiveAuthenticationChallenge:方法來(lái)處理認(rèn)證。

在認(rèn)證處理代理方法中,我們需要確認(rèn)認(rèn)證保護(hù)空間是否有NSURLAuthenticationMethodServerTrust類(lèi)型的認(rèn)證,如果有,則從保護(hù)空間獲取serverTrust信息。

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

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

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