尝试了解 URLSession 身份验证挑战

Rya*_*TCB 4 nsurlsessiondownloadtask swift urlauthenticationchallenges

我正在尝试从 URL 下载 PDF。

private func downloadSessionWithFileURL(_ url: URL){
    var request = URLRequest(url: url)
    
    request.addValue("gzip, deflate", forHTTPHeaderField: "Accept-Encoding")
   
    let sessionConfig = URLSessionConfiguration.default
    
    let session = URLSession(configuration: sessionConfig, delegate: self, delegateQueue: nil)
    session.downloadTask(with: request).resume()      
}
Run Code Online (Sandbox Code Playgroud)

这调用了它的委托方法

func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
    if challenge.previousFailureCount > 0 {
          completionHandler(Foundation.URLSession.AuthChallengeDisposition.cancelAuthenticationChallenge, nil)
    }
    if let serverTrust = challenge.protectionSpace.serverTrust {
      completionHandler(Foundation.URLSession.AuthChallengeDisposition.useCredential, URLCredential(trust: serverTrust))
} else {
      print("unknown state. error: \(String(describing: challenge.error))")
   }
}
Run Code Online (Sandbox Code Playgroud)

URLAuthenticationChallenges 保护空间始终是 serverTrust。当尝试访问 PDF 的 URL 时,它会将用户重定向到登录屏幕。我本以为会有另一个电话

func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void)
Run Code Online (Sandbox Code Playgroud)

要求用户输入他们的凭据,但没有。因此,下载任务尝试下载重定向 URL(登录屏幕)的内容。

我的问题是。

  1. 是什么触发了针对用户名和密码的 URLAuthenticationChallenge。它是 HTML 中的特定标头值吗?

  2. 对于来自服务器的用户名密码请求,我应该期待哪个 URLAuthenticationChallenge ProtectionSpace。

Ben*_*Ben 8

有两种不同的委托协议:用于 URLSession 本身及其任务。

URLSessionDelegate 具有:public func urlSession(_:didReceive:completionHandler:) URLSessionTaskDelegate 具有:public func urlSession(_:task:didReceive:completionHandler:)

URLSessionDelegate 用于解决服务器信任问题(例如,通过 Charles 或其他代理运行时允许 SSL 信任)。URLSessionTaskDelegate 用于对单个任务进行身份验证。

因此,要获得身份验证质询,请将其添加到您的类中:

extension MyClass: URLSessionTaskDelegate {

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

        if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodDefault ||
            challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodHTTPBasic {

            let credential = URLCredential(user: self.basicAuthUserName,
                                           password: self.basicAuthPassword,
                                           persistence: .forSession)

            completionHandler(.useCredential, credential)
        }
        else {
            completionHandler(.performDefaultHandling, nil)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)