Alamofire 5 委托中缺少 sessionDidReceiveChallenge
Missing sessionDidReceiveChallenge in Alamofire 5 delegate
我需要从 Alamofire 4 迁移到 5,但我缺少 sessionDidReceiveChallenge
委托回调
我以前在版本 4 中使用过这样的东西:
let manager = Alamofire.SessionManager(
configuration: URLSessionConfiguration.default
)
manager.delegate.sessionDidReceiveChallenge = { session, challenge in
let method = challenge.protectionSpace.authenticationMethod
if method == NSURLAuthenticationMethodClientCertificate {
return (.useCredential, self.cert.urlCredential())
}
if method == NSURLAuthenticationMethodServerTrust {
let trust = challenge.protectionSpace.serverTrust!
let credential = URLCredential(trust: trust)
return (.useCredential, credential)
}
return (.performDefaultHandling, Optional.none)
}
但现在是版本 5,委托已更改为 SessionDelegate
class,但没有提供类似的功能
我尝试像这样使用 URLSession
的委托:
let delegate = SomeSessionDelegate()
let delegateQueue: OperationQueue = .init()
delegateQueue.underlyingQueue = .global(qos: .background)
let session = URLSession(
configuration: URLSessionConfiguration.af.default,
delegate: delegate,
delegateQueue: delegateQueue
)
let manager = Alamofire.Session(
session: session,
delegate: SessionDelegate(),
rootQueue: .global(qos: .background)
)
class SomeSessionDelegate: NSObject, URLSessionDelegate {
let cert = ...
func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
//same impl as before
}
}
我猜我在第 5 版中的实现是错误的,因为我停止接收响应回调
请告知如何在版本 5 中正确管理请求质询
无需覆盖 SessionDelegate
即可使用客户端证书。 Alamofire 将自动使用附加的 URLCredential
进行客户端证书挑战。只需将凭据附加到请求中即可:
AF.request(...)
.authenticate(with: clientCertCredential)
.response...
此外,您的服务器信任检查将 return 任何信任视为有效,这可能是一个安全问题。我会立即停止使用该代码。
对于会话级别的证书处理,我在 URLCredentialStorage
共享存储上使用 URLProtectionSpace
,然后将其设置为 Alamofire.Session
配置
这里有一个设置示例(端口 443 可能就足够了)
fileprivate func registerURLCredential() {
let storage = URLCredentialStorage.shared
do {
let credential: URLCredential = try loadURLCredential("certificate", password: "blablabla")
let url = URL.API
let host = url.host ?? ""
let ports: [Int] = [80, 443, url.port ?? 0]
for port in ports {
let space = URLProtectionSpace(
host: host,
port: port,
protocol: url.scheme,
realm: nil,
authenticationMethod: NSURLAuthenticationMethodClientCertificate
)
storage.set(credential, for: space)
}
} catch {
print(error)
}
}
fileprivate func createSession(_ configurationHandler: ((_ configuration: URLSessionConfiguration) -> Void)? = nil) -> Alamofire.Session {
let configuration = URLSessionConfiguration.af.default
registerURLCredential()
configuration.urlCredentialStorage = .shared
configurationHandler?(configuration)
let session = Session(
configuration: configuration,
requestQueue: .global(qos: .background),
serializationQueue: .global(qos: .background)
)
return session
}
一个简单的用途是:
let sesstion = createSession({ configuration in
configuration.httpMaximumConnectionsPerHost = 1
})
我需要从 Alamofire 4 迁移到 5,但我缺少 sessionDidReceiveChallenge
委托回调
我以前在版本 4 中使用过这样的东西:
let manager = Alamofire.SessionManager(
configuration: URLSessionConfiguration.default
)
manager.delegate.sessionDidReceiveChallenge = { session, challenge in
let method = challenge.protectionSpace.authenticationMethod
if method == NSURLAuthenticationMethodClientCertificate {
return (.useCredential, self.cert.urlCredential())
}
if method == NSURLAuthenticationMethodServerTrust {
let trust = challenge.protectionSpace.serverTrust!
let credential = URLCredential(trust: trust)
return (.useCredential, credential)
}
return (.performDefaultHandling, Optional.none)
}
但现在是版本 5,委托已更改为 SessionDelegate
class,但没有提供类似的功能
我尝试像这样使用 URLSession
的委托:
let delegate = SomeSessionDelegate()
let delegateQueue: OperationQueue = .init()
delegateQueue.underlyingQueue = .global(qos: .background)
let session = URLSession(
configuration: URLSessionConfiguration.af.default,
delegate: delegate,
delegateQueue: delegateQueue
)
let manager = Alamofire.Session(
session: session,
delegate: SessionDelegate(),
rootQueue: .global(qos: .background)
)
class SomeSessionDelegate: NSObject, URLSessionDelegate {
let cert = ...
func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
//same impl as before
}
}
我猜我在第 5 版中的实现是错误的,因为我停止接收响应回调
请告知如何在版本 5 中正确管理请求质询
无需覆盖 SessionDelegate
即可使用客户端证书。 Alamofire 将自动使用附加的 URLCredential
进行客户端证书挑战。只需将凭据附加到请求中即可:
AF.request(...)
.authenticate(with: clientCertCredential)
.response...
此外,您的服务器信任检查将 return 任何信任视为有效,这可能是一个安全问题。我会立即停止使用该代码。
对于会话级别的证书处理,我在 URLCredentialStorage
共享存储上使用 URLProtectionSpace
,然后将其设置为 Alamofire.Session
配置
这里有一个设置示例(端口 443 可能就足够了)
fileprivate func registerURLCredential() {
let storage = URLCredentialStorage.shared
do {
let credential: URLCredential = try loadURLCredential("certificate", password: "blablabla")
let url = URL.API
let host = url.host ?? ""
let ports: [Int] = [80, 443, url.port ?? 0]
for port in ports {
let space = URLProtectionSpace(
host: host,
port: port,
protocol: url.scheme,
realm: nil,
authenticationMethod: NSURLAuthenticationMethodClientCertificate
)
storage.set(credential, for: space)
}
} catch {
print(error)
}
}
fileprivate func createSession(_ configurationHandler: ((_ configuration: URLSessionConfiguration) -> Void)? = nil) -> Alamofire.Session {
let configuration = URLSessionConfiguration.af.default
registerURLCredential()
configuration.urlCredentialStorage = .shared
configurationHandler?(configuration)
let session = Session(
configuration: configuration,
requestQueue: .global(qos: .background),
serializationQueue: .global(qos: .background)
)
return session
}
一个简单的用途是:
let sesstion = createSession({ configuration in
configuration.httpMaximumConnectionsPerHost = 1
})