NSURLSession 与 NSURLAuthenticationMethodServerTrust —— 从零开始的“服务器信任质询”全流程
目标读者:刚接触 iOS 网络开发、准备理解 HTTPS 与证书校验细节的同学 出发点:搞清楚为什么会有“质询”、质询的触发时机、以及在 delegate 里怎么正确地处理它。
1. 质询到底是什么?
当 URLSession 发现需要某种额外凭据(credential)才能继续网络交互时,会暂停请求并向你抛出 authentication challenge。对 HTTPS 来说,最常见的触发类型就是 NSURLAuthenticationMethodServerTrust:
服务器把 X.509 证书链塞进 TLS 握手。
客户端(iOS TLS 实现 + ATS 默认策略)检查:
- 证书是否在有效期、是否被吊销;
- 证书链是否能追溯到系统或配置的受信根 CA;
- 证书的 CN/SAN 是否与请求的 host 完全匹配。
如果 全部 检查都能自动通过,URLSession 不会打扰你——直接走默认证书校验并继续请求。
只要 你实现了 session-level delegate 方法 urlSession(_:didReceive:completionHandler:),系统就会把步骤 2 的工作“交卷”给你——即使校验本来能自动通过。
🚩 所以:不实现该 delegate == 自动信任系统 CA + ATS 默认策略;实现 delegate == 你必须亲自裁定是否信任。
2. 质询出现的典型场景
生产环境,使用合法证书(Let’s Encrypt、GlobalSign…) | 你自己实现了 delegate,但只是想保留系统默认验证 | 再次调用 SecTrustEvaluateWithError,通过则 .useCredential |
内网/测试环境 使用自签名证书 | 系统根证书链里找不到颁发者 | 把自签根证书预装到 App Bundle 并做自定义信任 |
做 SSL Pinning(证书/公钥固定) | 你想缩短信任链,拒绝被“合法”但非预期的 CA 篡改 | 手动比对二进制证书或公钥哈希,然后再决定是否信任 |
使用 HTTP 抓包工具 (Charles、mitmproxy) | 代理伪造服务器证书,除非你安装其证书为根 CA | 开发调试时允许 Charles 证书;上线包一定要拒绝 |
3. 基础实现(Swift 5+)
/// 在创建 URLSession 时指定 delegate,而不是用 URLSession.shared
let session = URLSession(configuration: .default,
delegate: self,
delegateQueue: nil)
extension YourNetworkManager: URLSessionDelegate {
/// 系统对“服务器信任”发起的质询都会走到这里
func urlSession(_ session: URLSession,
didReceive challenge: URLAuthenticationChallenge,
completionHandler: @escaping (URLSes
评论前必须登录!
注册