App Transport Security
问题
ATS 是什么?如何配置 HTTPS 和证书校验?
答案
ATS 概述
App Transport Security(ATS)是 iOS 9 引入的安全机制,默认要求所有网络请求使用 HTTPS。
Info.plist - 例外配置
<key>NSAppTransportSecurity</key>
<dict>
<!-- 仅允许特定域名 HTTP -->
<key>NSExceptionDomains</key>
<dict>
<key>legacy-api.example.com</key>
<dict>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<true/>
</dict>
</dict>
</dict>
危险
不要使用 NSAllowsArbitraryLoads = YES 关闭所有 ATS 检查,App Store 审核可能被拒。
SSL Pinning(证书锁定)
防止中间人攻击,验证服务器证书:
class SSLPinningDelegate: NSObject, URLSessionDelegate {
func urlSession(_ session: URLSession,
didReceive challenge: URLAuthenticationChallenge,
completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
guard let serverTrust = challenge.protectionSpace.serverTrust,
let serverCert = SecTrustGetCertificateAtIndex(serverTrust, 0) else {
completionHandler(.cancelAuthenticationChallenge, nil)
return
}
// 获取服务器证书公钥 hash
let serverPublicKey = SecCertificateCopyKey(serverCert)!
let serverKeyData = SecKeyCopyExternalRepresentation(serverPublicKey, nil)! as Data
// 与内置公钥对比
let pinnedKeyHash = "内置的公钥哈希"
let serverKeyHash = SHA256.hash(data: serverKeyData).description
if serverKeyHash == pinnedKeyHash {
let credential = URLCredential(trust: serverTrust)
completionHandler(.useCredential, credential)
} else {
completionHandler(.cancelAuthenticationChallenge, nil)
}
}
}
常见面试问题
Q1: 证书锁定锁证书还是锁公钥?
答案:推荐锁公钥(Public Key Pinning)。证书有过期时间,锁证书需要频繁更新 App。公钥在证书续期时通常不变,更稳定。