Alamofire 4.9.1 sessionManager.delegate.sessionDidReceiveChallenge 未在 iOS 15 中分配

Alamofire 4.9.1 sessionManager.delegate.sessionDidReceiveChallenge is not getting assigned in iOS 15

我正在开发的 iOS 应用程序使用的是 Alamofire 4.9.1,以下代码在 iOS 14 及以下版本(但在 iOS 15)中执行时没有任何问题。

dataProvider.sessionDelegate.sessionDidReceiveChallenge = { _, challenge in
                
                print("CHALLENGE ACCEPTED")
                
                if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodClientCertificate {

                    return (URLSession.AuthChallengeDisposition.useCredential,
                            cert.urlCredential())
                }

                if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust {

                    return (URLSession.AuthChallengeDisposition.useCredential,
                            URLCredential(trust: challenge.protectionSpace.serverTrust!));
                }

                return (URLSession.AuthChallengeDisposition.performDefaultHandling,
                        Optional.none)
            }

,其中 cert 是在此之前初始化的 .pfx 证书。

这会阻止应用程序使用基于 TLS 1.2 证书的身份验证访问服务器上的信息。在 iOS 13 和 14(支持的 iOS 版本从 13 开始)打印语句执行,但由于某种原因在 iOS 15 中不执行。在 iOS 13 和 14,在 Alamofire 的 SessionDelegate.swift,

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

被调用,但在 iOS 15 中被对

的调用所取代
open func urlSession(
        _ session: URLSession,
        task: URLSessionTask,
        didReceive challenge: URLAuthenticationChallenge,
        completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void)

知道是什么原因导致的以及如何解决吗?提前谢谢你。

有趣的是,这可能已经改变,因为记录的行为没有:NSURLAuthenticationMethodServerTrust挑战应该由会话的委托接收,而不是任务的,除非会话委托根本不实现该方法.我会向 Apple 报告此问题,以便他们可以修复文档或委托回调本身。

无论如何,Alamofire 4 不受支持,此问题将不会得到修复。请更新到 Alamofire 5,它通过仅实现此方法的 URLSessionTaskDelegate 版本并为此逻辑提供单个挂钩来纠正此问题。

我通过修改 Alamofire pod 本身的 SessionDelegate.swift 文件设法解决了这个问题。即,我在 SessionDelegate.swift 文件中初始化证书并将其 urlCredential 属性 传递给

中任务委托的凭证 属性
open func urlSession(
    _ session: URLSession,
    task: URLSessionTask,
    didReceive challenge: URLAuthenticationChallenge,
    completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void)

voilà,成功了。

所以我重新定义了 class (PKCS12),它让我在 SessionDelegate.swift 文件中初始化证书,上面函数的主体现在看起来像这样:

if let taskDidReceiveChallenge = taskDidReceiveChallenge {
        let result = taskDidReceiveChallenge(session, task, challenge)
        completionHandler(result.0, result.1)
    } else if let delegate = self[task]?.delegate {
        // this gets executed in iOS 15 and we need to get a credential in order for the delegate to successfully set the disposition required for getting data from the server
        let cert = PKCS12.init(mainBundleResource: "\(certNameHere)",
                               resourceType: "pfx",
                               password: "%^&^%*&")
        delegate.credential = cert.urlCredential()
        delegate.urlSession(
            session,
            task: task,
            didReceive: challenge,
            completionHandler: completionHandler
        )
    } else {
        urlSession(session, didReceive: challenge, completionHandler: completionHandler)
    }

这已经为我们解决了这个问题,我希望它对其他可能遇到与 iOS 15 和 Alamofire 4.9.1 类似问题的人有所帮助。感谢阅读。