You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在URLSession中使用URLCredential实现非基础认证

在Swift中用URLSession结合URLCredential实现非基础认证的用户名密码验证

要实现非基础认证的用户名密码验证,你不能直接用URLSession.shared——它的代理是系统内部的,没法自定义。得自己创建URLSession并设置代理,处理服务器抛出的认证挑战,具体步骤如下:

1. 自定义URLSession并实现代理

先让你的类遵循URLSessionDelegate协议,创建带代理的URLSession实例:

class YourNetworkHandler: URLSessionDelegate {
    private var customSession: URLSession!
    
    init() {
        let config = URLSessionConfiguration.default
        // 初始化自定义Session,绑定当前类为代理,代理队列用主队列(也可以用后台队列,根据需求调整)
        customSession = URLSession(configuration: config, delegate: self, delegateQueue: OperationQueue.main)
    }
}

2. 实现认证挑战处理方法

在代理类里实现urlSession(_:didReceive:completionHandler:)方法,这是处理认证请求的核心:

extension YourNetworkHandler {
    func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
        let protectionSpace = challenge.protectionSpace
        
        // 跳过服务器信任认证(比如HTTPS证书验证,交给系统默认处理)
        if protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust {
            completionHandler(.performDefaultHandling, nil)
            return
        }
        
        // 处理用户名密码类型的认证(支持Digest等非基础认证)
        let username = "你的用户名"
        let password = "你的密码"
        // 创建凭证:persistence选.forSession表示仅当前会话有效,也可选.permanent(存钥匙串)或.none
        let credential = URLCredential(user: username, password: password, persistence: .forSession)
        // 告诉Session使用这个凭证完成认证
        completionHandler(.useCredential, credential)
    }
}

3. 修改请求代码使用自定义Session

把你原来的startLoad方法放到代理类里,替换成自定义的Session发起请求:

extension YourNetworkHandler {
    func startLoad() {
        guard let url = URL(string: "https://www.abcde-test-url.com/") else {
            print("无效URL")
            return
        }
        
        let task = customSession.dataTask(with: url) { data, response, error in
            if let error = error {
                print("客户端错误: \(error.localizedDescription) \n")
                return
            }
            
            guard let data = data, let httpResponse = response as? HTTPURLResponse else {
                print("无数据或无响应")
                return
            }
            
            if httpResponse.statusCode == 200 {
                print("请求成功,返回数据: \(data)")
            } else {
                print("错误状态码: \(httpResponse.statusCode)\n")
            }
        }
        task.resume()
    }
}

使用示例

在需要发起请求的地方,初始化这个网络处理类并调用方法:

let handler = YourNetworkHandler()
handler.startLoad()

关键说明

  • 不管是Digest还是其他非基础的用户名密码认证,URLSession都会自动处理对应的认证流程,你只需要提供正确的凭证即可,不用手动构造认证头。
  • 凭证的persistence参数可根据需求调整:.forSession仅当前App会话有效,.permanent会保存到系统钥匙串,.none则不保存。
  • 如果服务器同时要求HTTPS证书验证,上面的代码已经跳过了这部分(交给系统默认处理),如果需要自定义证书验证,可以在NSURLAuthenticationMethodServerTrust分支里添加逻辑。

内容的提问来源于stack exchange,提问作者Keita Sumiya

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 08:45:18