Alamofire 5 代表中缺少 sessionDidReceiveChallenge

Posted

技术标签:

【中文标题】Alamofire 5 代表中缺少 sessionDidReceiveChallenge【英文标题】:Missing sessionDidReceiveChallenge in Alamofire 5 delegate 【发布时间】:2020-05-26 14:43:18 【问题描述】:

我需要从 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 类,但未提供类似功能

我尝试像这样使用来自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 中正确管理请求挑战

【问题讨论】:

+1,你能用 Alamofire 5 修复它吗?如果是这样,请将其添加到某处以供参考,因为我也面临问题。 是的,我会在一分钟内发布我所做的事情 @Dhruv 如果您使用URLProtectionSpace,则不需要委托调用 @zombie 你解决了这个问题吗?如果是,请分享代码。谢谢! 我确实分享了代码,这是我的答案 【参考方案1】:

无需覆盖SessionDelegate 即可使用客户端证书。 Alamofire 将自动使用附加的URLCredential 进行客户端证书挑战。只需将凭据附加到请求中即可:

AF.request(...)
    .authenticate(with: clientCertCredential)
    .response...

此外,您的服务器信任检查将返回任何有效的信任,这可能是一个安全问题。我会立即停止使用该代码。

【讨论】:

感谢您不接受任何证书的建议,但在我的情况下并不重要,因为整个应用程序只允许连接到一个主机 有没有办法将证书添加到会话而不是单个请求(除了在请求上写扩展) 是的,您可以使用自定义URLCredentialStorage 设置URLSessionConfiguration 或使用shared URLCredentialStorage。您可以为客户端证书空间设置默认凭据。【参考方案2】:

对于会话级别的证书处理,我在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之前已经使用过this approach 您似乎仍然可以通过您的方法生成URLCredential,然后您可以在存储中或在单个请求中使用它 嘿,我开了一个question。请检查

以上是关于Alamofire 5 代表中缺少 sessionDidReceiveChallenge的主要内容,如果未能解决你的问题,请参考以下文章

响应中缺少 Alamofire 参数

你如何在 Alamofire 5 中实现 RequestAdapter?

如何在 alamofire 5.0.2 版本中设置自定义超时

Alamofire 会话配置未反映在请求中

Alamofire POST 请求,正文中有一个简单的字符串作为参数,标头仍然显示缺少的参数值

Alamofire源码学习