SessionDelegate
SessionDelegate 集所有URLSessionDelegate及其子类于一生
包含一下子类功能
basic:
- URLSessionDelegate
extend:
URLSessionTaskDelegate
URLSessionDataDelegate
URLSessionDonwloadDelegate
URLSessionStreamDelegate
这样一个SessionDelegate类,就集成了所有session代理功能,不要针对某种具体的session,去初始化相应的URLSessionDelegate子类
Session delegate handle
Alamofire 提供用户多种处理session消息的方法
- SessionDelegate 默认处理
- SessionDelegate userHandleWithCompletion(message)
- SessionDelegate userHandle(message)
- TaskDelegate userHandle(message)
- TaskDelegate 默认处理
那么这么多处理方法,不会冲突吗? 比如一个向左一个向右的问题的情况下如何处理?
看下这个代码就明白了
SessionDelegate file
/// Overrides default behavior for URLSessionDelegate method `urlSession(_:didReceive:completionHandler:)`.
open var sessionDidReceiveChallenge: ((URLSession, URLAuthenticationChallenge) -> (URLSession.AuthChallengeDisposition, URLCredential?))?
/// Overrides all behavior for URLSessionDelegate method `urlSession(_:didReceive:completionHandler:)` and requires the caller to call the `completionHandler`.
open var sessionDidReceiveChallengeWithCompletion: ((URLSession, URLAuthenticationChallenge, @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) -> Void)?
open func urlSession(
_ session: URLSession,
task: URLSessionTask,
didReceive challenge: URLAuthenticationChallenge,
completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void)
{
// case1: taskDidReceiveChallengeWithCompletion 不为空,则执行该case
guard taskDidReceiveChallengeWithCompletion == nil else {
taskDidReceiveChallengeWithCompletion?(session, task, challenge, completionHandler)
return
}
// case2: taskDidReceiveChallenge 不为空,则执行该case
if let taskDidReceiveChallenge = taskDidReceiveChallenge {
let result = taskDidReceiveChallenge(session, task, challenge)
completionHandler(result.0, result.1)
} else if let delegate = self[task]?.delegate { // 触发taskDelegate
delegate.urlSession(
session,
task: task,
didReceive: challenge,
completionHandler: completionHandler
)
} else { // 默认处理
urlSession(session, didReceive: challenge, completionHandler: completionHandler)
}
}
TaskDelegate Default Handle
@objc(URLSession:task:didReceiveChallenge:completionHandler:)
func urlSession(
_ session: URLSession,
task: URLSessionTask,
didReceive challenge: URLAuthenticationChallenge,
completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void)
{
var disposition: URLSession.AuthChallengeDisposition = .performDefaultHandling
var credential: URLCredential?
if let taskDidReceiveChallenge = taskDidReceiveChallenge {
(disposition, credential) = taskDidReceiveChallenge(session, task, challenge)
} else if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust {
let host = challenge.protectionSpace.host
if
let serverTrustPolicy = session.serverTrustPolicyManager?.serverTrustPolicy(forHost: host),
let serverTrust = challenge.protectionSpace.serverTrust
{
if serverTrustPolicy.evaluate(serverTrust, forHost: host) {
disposition = .useCredential
credential = URLCredential(trust: serverTrust)
} else {
disposition = .cancelAuthenticationChallenge
}
}
} else {
if challenge.previousFailureCount > 0 {
disposition = .rejectProtectionSpace
} else {
credential = self.credential ?? session.configuration.urlCredentialStorage?.defaultCredential(for: challenge.protectionSpace)
if credential != nil {
disposition = .useCredential
}
}
}
completionHandler(disposition, credential)
}
那么阅读这段代码优先级很明了了,优先级如下:
- SessionDelegate userHandleWithCompletion(message)
- SessionDelegate userHandle(message)
- TaskDelegate userHandle(message)
- TaskDelegate 默认处理
- SessionDelegate 默认处理
SessionDelegate Default Handle
open func urlSession(
_ session: URLSession,
didReceive challenge: URLAuthenticationChallenge,
completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void)
{
guard sessionDidReceiveChallengeWithCompletion == nil else {
sessionDidReceiveChallengeWithCompletion?(session, challenge, completionHandler)
return
}
var disposition: URLSession.AuthChallengeDisposition = .performDefaultHandling
var credential: URLCredential?
if let sessionDidReceiveChallenge = sessionDidReceiveChallenge {
(disposition, credential) = sessionDidReceiveChallenge(session, challenge)
} else if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust {
let host = challenge.protectionSpace.host
if
let serverTrustPolicy = session.serverTrustPolicyManager?.serverTrustPolicy(forHost: host),
let serverTrust = challenge.protectionSpace.serverTrust
{
if serverTrustPolicy.evaluate(serverTrust, forHost: host) {
disposition = .useCredential
credential = URLCredential(trust: serverTrust)
} else {
disposition = .cancelAuthenticationChallenge
}
}
}
completionHandler(disposition, credential)
}
SessionDelegate Default Handle
和 TaskDeleaget Default Handle
, 处理流程基本一致使用serverTrustPolicy 对服务端证书进行评估
ServerTrustPolicy
这里看下最主要的分支
case let .pinCertificates(pinnedCertificates, validateCertificateChain, validateHost):
// 验证整个证书链
if validateCertificateChain {
let policy = SecPolicyCreateSSL(true, validateHost ? host as CFString : nil)
SecTrustSetPolicies(serverTrust, policy)
SecTrustSetAnchorCertificates(serverTrust, pinnedCertificates as CFArray)
SecTrustSetAnchorCertificatesOnly(serverTrust, true)
serverTrustIsValid = trustIsValid(serverTrust)
} else {
// 这个就只需要命中客户端一个证书即可
let serverCertificatesDataArray = certificateData(for: serverTrust)
let pinnedCertificatesDataArray = certificateData(for: pinnedCertificates)
outerLoop: for serverCertificateData in serverCertificatesDataArray {
for pinnedCertificateData in pinnedCertificatesDataArray {
if serverCertificateData == pinnedCertificateData {
serverTrustIsValid = true
break outerLoop
}
}
}
}