服務器信任質詢

NSURLSession 與 NSURLAuthenticationMethodServerTrust —— 從零開始的“服務器信任質詢”全流程

目標讀者:剛接觸 iOS 網絡開發、準備理解 HTTPS 與證書校驗細節的同學
出發點:搞清楚為什么會有“質詢”、質詢的觸發時機、以及在 delegate 里怎么正確地處理它


1. 質詢到底是什么?

URLSession 發現需要某種額外憑據(credential)才能繼續網絡交互時,會暫停請求并向你拋出 authentication challenge。對 HTTPS 來說,最常見的觸發類型就是 NSURLAuthenticationMethodServerTrust

  1. 服務器把 X.509 證書鏈塞進 TLS 握手。

  2. 客戶端(iOS TLS 實現 + ATS 默認策略)檢查:

    • 證書是否在有效期、是否被吊銷;
    • 證書鏈是否能追溯到系統或配置的受信根 CA;
    • 證書的 CN/SAN 是否與請求的 host 完全匹配。
  3. 如果 全部 檢查都能自動通過,URLSession 不會打擾你——直接走默認證書校驗并繼續請求。

  4. 只要 你實現了 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 (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {guard challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust,let serverTrust = challenge.protectionSpace.serverTrust else {// 交給系統默認處理(例如 HTTP Basic、客戶端證書等)completionHandler(.performDefaultHandling, nil)return}// 1?? 讓系統再跑一次標準評估if SecTrustEvaluateWithError(serverTrust, nil) {let credential = URLCredential(trust: serverTrust)completionHandler(.useCredential, credential)   // 繼續請求} else {completionHandler(.cancelAuthenticationChallenge, nil) // 終止}}
}

iOS 13- 及更早版本用 SecTrustEvaluate;iOS 13+ 強烈建議改用 SecTrustEvaluateWithError 以拿到 CFError 信息并避免阻塞 main thread。

Objective-C 版本(簡化)

- (void)URLSession:(NSURLSession *)sessiondidReceiveChallenge:(NSURLAuthenticationChallenge *)challengecompletionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler {if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {SecTrustRef trust = challenge.protectionSpace.serverTrust;if (SecTrustEvaluateWithError(trust, NULL)) {NSURLCredential *cred = [NSURLCredential credentialForTrust:trust];completionHandler(NSURLSessionAuthChallengeUseCredential, cred);} else {completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil);}return;}completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil);
}

4. 深入:自簽名證書與 SSL Pinning

4.1 只信任 Bundle 中的根證書

if let certPath = Bundle.main.path(forResource: "myRootCA", ofType: "cer"),let certData = try? Data(contentsOf: URL(fileURLWithPath: certPath)),let rootCert = SecCertificateCreateWithData(nil, certData as CFData) {SecTrustSetAnchorCertificates(serverTrust, [rootCert] as CFArray)SecTrustSetAnchorCertificatesOnly(serverTrust, true)if SecTrustEvaluateWithError(serverTrust, nil) {completionHandler(.useCredential, URLCredential(trust: serverTrust))} else {completionHandler(.cancelAuthenticationChallenge, nil)}
}

SecTrustSetAnchorCertificatesOnly=true 的效果是“把系統根 CA 全部踢出,僅信任我給定的這一束證書”。

4.2 公鑰 Pinning(效率更高,證書續期更靈活)

guard let serverTrust = challenge.protectionSpace.serverTrust else { ... }
guard SecTrustEvaluateWithError(serverTrust, nil) else { ... }let serverPublicKey = SecTrustCopyKey(serverTrust)!
let serverKeyData   = SecKeyCopyExternalRepresentation(serverPublicKey, nil)! as Data
let serverKeyHash   = SHA256(serverKeyData) // 自己寫或 CryptoKitif pinnedHashes.contains(serverKeyHash) {completionHandler(.useCredential, URLCredential(trust: serverTrust))
} else {completionHandler(.cancelAuthenticationChallenge, nil)
}

5. 典型錯誤排查清單

現象根因快速定位
Code -999 “已取消”你在 delegate 里返回了 .cancelAuthenticationChallenge.rejectProtectionSpace打斷點檢查 challenge.protectionSpace
Code -1200 “SSL error”證書鏈無效 / ATS 阻止弱加密觀察 Console,中會打印 ATS policy requires...
Charles 無法抓包ATS 拒絕了 Charles 證書;或你啟用了 Pinning臨時將 NSExceptionDomains 加入 Info.plist,或關閉 Pinning
偶發 ServerTrust 失敗服務器有多個證書鏈、SNI/host 不一致手動訪問 https://hostopenssl s_client -servername host -connect ip:443

6. 最佳實踐速覽

  • 不做弱校驗。切勿直接 .useCredential 而不跑 SecTrustEvaluateWithError,那等同于“信任一切”,上線會被審核拒絕。
  • Pin 公鑰而非整張證書,減少因證書續期頻繁發版。
  • 按需配置 ATS。絕大多數生產 HTTPS 服務都可以滿足 ATS 默認要求:TLS 1.2+、至少 RSA 2048 或 ECC 256 、SHA-256 簽名。
  • 調試與上線嚴格隔離。把抓包例外、測試根證書全部寫在 #if DEBUG ... #endif 分支中。

結語

NSURLAuthenticationMethodServerTrust 看似只是“系統多問一句,你到底信不信任這臺服務器?”,但背后承載的是 PKITLS 乃至你 App 用戶的數據安全。真正的安全措施都在“默認正確”與“最小權限”

默認讓系統校驗一切,只有當你非常確定要改時才介入,并且介入后要保證比系統 更嚴格 而不是更松。

掌握這些基礎,你就能輕松向自簽環境、抓包調試甚至 SSL Pinning 過渡,也能對任何“為什么連接被取消?”作出快速診斷。愿你寫出的每一行網絡代碼都能經得起安全審計與真實攻擊的考驗。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/908449.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/908449.shtml
英文地址,請注明出處:http://en.pswp.cn/news/908449.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

MCP協議重構AI Agent生態:萬能插槽如何終結工具孤島?

前言 在人工智能技術快速發展的2025年,MCP(Model Context Protocol,模型上下文協議)正逐漸成為AI Agent生態系統的關鍵基礎設施。這一由Anthropic主導的開放協議,旨在解決AI模型與外部工具和數據源之間的連接難題,被業界形象地稱…

測試 FreeSWITCH 的 mod_loopback

bgapi originate loopback/answer,park/default/inline park inline show channels as xml show calls as xml 有 2 個 channels 有 2 個 calls 比較有意思 在 loopback-a 是播放 wav 在 loopback-b 上可以錄音 這就是回環 有什么用呢? 除了做測試&#x…

三維GIS開發cesium智慧地鐵教程(4)城市白模加載與樣式控制

一、添加3D瓦片 <!-- 核心依賴引入 --> <script src"../cesium1.99/Build/Cesium/Cesium.js"></script> <link rel"stylesheet" href"../cesium1.99/Build/Cesium/Widgets/widgets.css"><!-- 模型數據路徑 --> u…

Unity 中的顏色空間

一、顏色空間基本概念疑問 1、什么是顏色空間&#xff1f; 顏色空間是一個數學模型或系統&#xff0c;它定義了一套規則和方法&#xff0c;用來精確地描述、表示和組織顏色。? 可以把它想象成一個三維坐標系?&#xff08;或者有時更多維&#xff09; 每個維度代表一…

Mac下Android Studio掃描根目錄卡死問題記錄

環境信息 操作系統: macOS 15.5 (Apple M2芯片)Android Studio版本: Meerkat Feature Drop | 2024.3.2 Patch 1 (Build #AI-243.26053.27.2432.13536105, 2025年5月22日構建) 問題現象 在項目開發過程中&#xff0c;提示一個依賴外部頭文件的cpp源文件需要同步&#xff0c;點…

Python----目標檢測(YOLO簡介)

一、 YOLO簡介 [YOLO](You Only Look Once&#xff09;是一種流行的物體檢測和圖像分割模型&#xff0c; 由華盛頓大學的約瑟夫-雷德蒙&#xff08;Joseph Redmon&#xff09;和阿里-法哈迪&#xff08;Ali Farhadi&#xff09;開發&#xff0c;YOLO 于 2015 年推出&#xff0c…

OLED(SSD306)移植全解-基于IIC

OLED&#xff08;SSD306&#xff09;移植全解-基于IIC 一&#xff0c;什么是oled?二&#xff0c;什么是IIC協議三&#xff0c;IIC通信流程&#xff1a;四&#xff0c;針對SSD1306的IIC通信流程&#xff08;結合芯片手冊版&#xff09;1&#xff0c;主機發送起始信號2&#xff…

LangChain【7】之工具創建和錯誤處理策略

文章目錄 一 LangChain 自定義工具概述二創建自定義工具的三種方法2.1 方法一&#xff1a;tool 裝飾器2.1.1 同步方法案例2.1.2 工具描述方式1&#xff1a;傳參2.1.3 工具描述方式2&#xff1a;文檔字符串 2.2 方法二&#xff1a;StructuredTool類2.2.1 StructuredTool創建自定…

【信息系統項目管理師-選擇真題】2025上半年(第二批)綜合知識答案和詳解(回憶版)

更多內容請見: 備考信息系統項目管理師-專欄介紹和目錄 文章目錄 【第1題】【第2題】【第3題】【第4題】【第5題】【第6題】【第7題】【第8題】【第9題】【第10題】【第11題】【第12題】【第13題】【第14題】【第15題】【第16題】【第17題】【第18題】【第19題】【第20題】【第…

「EN 18031」訪問控制機制(ACM - 1):智能路由器的安全守衛

家用路由器要是出口歐洲&#xff0c;可得留意歐盟EN18031標準里的訪問控制機制。以路由器為例&#xff0c;訪問控制機制&#xff08;ACM&#xff09;能決定誰能連入網絡、訪問哪些網站。比如通過設置不同的用戶角色和權限&#xff0c;家長可以限制孩子設備的上網時間和可訪問的…

關于項目多語言化任務的概述

今天的任務一個是關于多語言化的&#xff0c;也就是i18n&#xff0c;我需要做的呢首先是知道項目多語言是怎么實現的&#xff0c;一般情況下沒有多語言化這個功能的時候&#xff0c;我們會寫一個頁面&#xff0c;默認是英文&#xff0c;然后里面的文本都是英文&#xff0c;那么…

護網行動面試試題(2)

文章目錄 51、常見的安全工具有哪些&#xff1f;52、說說Nmap工具的使用&#xff1f;53、近幾年HW常見漏洞有哪些&#xff1f;54、HW 三&#xff08;四&#xff09;大洞56、獲得文件讀取漏洞&#xff0c;通常會讀哪些文件57、了解過反序列化漏洞嗎&#xff1f;58、常見的框架漏…

Transformer-BiGRU多變量時序預測(Matlab完整源碼和數據)

Transformer-BiGRU多變量時序預測&#xff08;Matlab完整源碼和數據&#xff09; 目錄 Transformer-BiGRU多變量時序預測&#xff08;Matlab完整源碼和數據&#xff09;效果一覽基本介紹程序設計參考資料 效果一覽 基本介紹 1.Matlab實現Transformer-BiGRU多變量時間序列預測&…

SOC-ESP32S3部分:31-ESP-LCD控制器庫

飛書文檔https://x509p6c8to.feishu.cn/wiki/Syy3wsqHLiIiQJkC6PucEJ7Snib ESP 系列芯片可以支持市場上常見的 LCD&#xff08;如 SPI LCD、I2C LCD、并行 LCD (Intel 8080)、RGB/SRGB LCD、MIPI DSI LCD 等&#xff09;所需的各種時序。esp_lcd 控制器為上述各類 LCD 提供了一…

蘋果電腦深度清理,讓老舊Mac重煥新生

在日常使用蘋果電腦的過程中&#xff0c;隨著時間推移&#xff0c;系統內會積累大量冗余數據&#xff0c;導致電腦運行速度變慢、磁盤空間緊張。想要讓設備恢復流暢&#xff0c;蘋果電腦深度清理必不可少。那么&#xff0c;如何進行蘋果電腦深度清理呢&#xff1f;接下來為你詳…

如何處理React中表單的雙向數據綁定?

在前端開發中&#xff0c;雙向數據綁定&#xff08;Two-way Data Binding&#xff09;是指視圖&#xff08;View&#xff09;與數據模型&#xff08;Model&#xff09;之間保持同步&#xff1a;當模型發生變化時&#xff0c;視圖會自動更新&#xff1b;當視圖&#xff08;用戶輸…

手機上網可以固定ip地址嗎?詳細解析

在移動互聯網時代&#xff0c;手機已成為人們日常上網的主要設備之一。無論是工作、學習還是娛樂&#xff0c;穩定的網絡連接都至關重要。許多用戶對IP地址的概念有所了解&#xff0c;尤其是固定IP地址的需求。那么&#xff0c;手機上網能否固定IP地址&#xff1f;又該如何實現…

Spring Boot + Prometheus 實現應用監控(基于 Actuator 和 Micrometer)

文章目錄 Spring Boot Prometheus 實現應用監控&#xff08;基于 Actuator 和 Micrometer&#xff09;環境準備示例結構啟動和驗證驗證 Spring Boot 應用Prometheus 抓取配置&#xff08;靜態方式&#xff09;Grafana 面板配置總結 Spring Boot Prometheus 實現應用監控&…

rk3588 上運行smolvlm-realtime-webcam,將視頻轉為文字描述

smolvlm-realtime-webcam 是一個開源項目&#xff0c;結合了輕量級多模態模型 SmolVLM 和本地推理引擎 llama.cpp&#xff0c;能夠在本地實時處理攝像頭視頻流&#xff0c;生成自然語言描述&#xff0c; 開源項目地址 https://github.com/ngxson/smolvlm-realtime-webcamhttps…

原生js操作元素類名(classList,classList.add...)

1、classList classList屬性是一個只讀屬性&#xff0c;返回元素的類名&#xff0c;作為一個DOMTokenList集合(用于在元素中添加&#xff0c;移除及切換css類) length:返回類列表中類的數量&#xff0c;該屬性是只讀的 <style> .lis { width: 200px; …