跳到主要内容

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。公钥在证书续期时通常不变,更稳定。

相关链接