SSL/TLS — 加密移动应用与服务器之间数据的密码协议,保证流量的机密性和完整性。根据Apple(2026年)的数据,App Transport Security默认在所有iOS设备上阻止TLS 1.2以下的连接。TLS 1.3与TLS 1.2相比,将握手时间缩短了2倍,改善了移动应用的UX。
要点
SSL(安全套接层)和TLS(传输层安全)—— 确保通过网络安全传输数据的密码协议。SSL由Netscape在1990年代开发,由于POODLE和BEAST漏洞,在3.0版本后被宣布过时。TLS作为其继任者,经历了1.0、1.1、1.2和1.3版本——目前只有TLS 1.2和TLS 1.3被认为是现代的。所有现代移动平台都要求网络连接使用TLS,App Store和Google Play在审核阶段会对此进行检查。
没有TLS,应用和服务器之间的流量以明文形式传输——同一Wi-Fi网络中的任何人都可以使用Wireshark或tcpdump截获用户名、密码、令牌和用户的个人数据。TLS加密所有传输的数据(传输层加密),并通过X.509证书链验证服务器的真实性。根据IETF(2018年),TLS 1.3仅使用现代AEAD加密算法(AES-GCM、ChaCha20-Poly1305),排除了RC4和3DES等过时算法。
HTTPS(HTTP安全)—— 是基于TLS的HTTP。当移动应用通过https://发出请求时,它首先与服务器建立TLS连接,然后通过加密通道传输HTTP标头和请求体。没有HTTPS,任何严肃的API都不应该工作——这是基本的安全卫生。根据OWASP(2026年),不安全连接位列移动应用三大漏洞之一。
TLS握手 — 在客户端和服务器之间建立安全连接的过程。双方协商协议版本,选择密码套件,通过非对称密码学交换密钥,并验证证书。在TLS 1.2中,握手需要2次往返时间(2 RTT):客户端→服务器发送ClientHello,服务器→客户端发送ServerHello和Certificate,然后发送Finished消息。TLS 1.3将此过程缩短为1 RTT。
第一阶段:ClientHello — 客户端发送支持的TLS版本、密码套件列表和随机数。服务器用ServerHello响应,选择版本和密码套件,发送其X.509证书(Certificate)和ServerHelloDone消息。客户端通过受信任的证书颁发机构(CA)链验证证书,生成预主密钥,用证书中的公钥加密并发送到ClientKeyExchange中的服务器。之后,双方生成会话密钥并交换ChangeCipherSpec和Finished消息。从此刻起,所有数据都进行对称加密。
import Security
let url = URL(string: "https://api.example.com")!
let session = URLSession(configuration: .default,
delegate: self,
delegateQueue: nil)
func urlSession(
_ session: URLSession,
didReceive challenge: URLAuthenticationChallenge,
completionHandler: @escaping (URLSession.AuthChallengeDisposition,
URLCredential?) -> Void
) {
let trust = challenge.protectionSpace.serverTrust
guard let trust else {
completionHandler(.cancelAuthenticationChallenge, nil)
return
}
completionHandler(.useCredential, URLCredential(trust: trust))
}
通过URLSessionDelegate在iOS上处理URLAuthenticationChallenge的示例。每次TLS握手时都会调用此方法,允许应用自定义验证服务器证书。对于生产环境,通过SecTrustEvaluateWithError添加证书验证并与预先保存的指纹进行比较——然后才调用useCredential。
TLS 1.3(RFC 8446,2018年)—— 该协议10年来的首次重大更新。主要改进:握手减少到1 RTT(重新连接时为0 RTT),删除了过时的密码套件(RSA密钥交换、CBC模式),强制前向保密(PFS)以及通过签名记录防止降级攻击。根据Qualys SSL Labs(2026年)的数据,TLS 1.3凭借PFS即使在长期服务器密钥被泄露时也能提供保护。
| 特性 | TLS 1.2 | TLS 1.3 |
|---|---|---|
| 握手 | 2 RTT(完整) | 1 RTT(PSK时为0 RTT) |
| 密码套件 | 30+种组合(RSA、DH、ECDH) | 5种AEAD套件(AES-GCM、ChaCha20) |
| 前向保密 | 可选(DHE、ECDHE) | 强制(所有套件) |
| iOS支持 | iOS 5+ | iOS 12+ |
| Android支持 | Android 4.0+ | Android 10+ |
| 过时算法 | RSA、CBC、RC4、3DES | 已完全移除 |
0-RTT(零往返时间) — TLS 1.3的功能,允许客户端在通过PSK(预共享密钥)重新连接时立即与ClientHello一起发送数据。这加速了移动应用中后续屏幕的加载,特别是当频繁向同一服务器发送请求时。但是,0-RTT数据无法抵御重放攻击——可以被拦截并重新发送。仅对无副作用的幂等请求(GET、PUT)使用0-RTT。
App Transport Security(ATS) — Apple的机制,要求使用TLS 1.2或更高版本的HTTPS连接,自iOS 9起默认启用。ATS阻止所有HTTP连接和TLS低于1.2的HTTPS。开发者可以通过Info.plist中的NSAppTransportSecurity为特定域配置例外,但Apple建议尽量减少例外并尽量使用HTTPS。违反ATS要求是在App Store审核时拒绝应用的原因。
<!-- Info.plist — App Transport Security -->
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<false/>
<key>NSExceptionDomains</key>
<dict>
<key>cdn.example.com</key>
<dict>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<false/>
<key>NSExceptionMinimumTLSVersion</key>
<string>TLSv1.2</string>
</dict>
</dict>
<key>NSAllowsLocalNetworking</key>
<true/>
</dict>
Info.plist中的ATS配置。NSAllowsArbitraryLoads设置为false——所有连接必须使用HTTPS。对于域名cdn.example.com,设置了最低TLS 1.2版本,NSAllowsLocalNetworking=true允许本地网络的HTTP(对开发服务器有用)。Apple强烈建议不要在没有NSExceptionDomains的情况下启用NSAllowsArbitraryLoads——这应该是例外,而不是通用规则。
Network Security Config — Android用于配置HTTPS和TLS而无需修改Java/Kotlin代码的机制。配置在XML文件network_security_config.xml中定义,并通过android:networkSecurityConfig属性在AndroidManifest中连接。支持配置受信任的证书(用户和系统CA)、Certificate Pinning、禁用明文HTTP、调试覆盖和流量重定向。
<!-- res/xml/network_security_config.xml -->
<network-security-config>
<base-config cleartextTrafficPermitted="false">
<trust-anchors>
<certificates src="system" />
</trust-anchors>
</base-config>
<domain-config cleartextTrafficPermitted="false">
<domain includeSubdomains="true">api.example.com</domain>
<pin-set expiration="2027-01-01">
<pin digest="SHA-256">
47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=
</pin>
</pin-set>
</domain-config>
</network-security-config>
Android的Network Security Config。Base-config禁止明文流量,仅信任系统CA证书(不信任用户证书——防止用户安装MitM证书)。api.example.com的Domain-config包含带有证书SHA-256指纹的pin-set。如果服务器证书在指定的到期日期之前更改,连接将被拒绝——这是Certificate Pinning的严格形式。
Certificate Pinning — 在应用代码中固定服务器证书或公钥的技术。每次TLS握手时,客户端将服务器证书与预先保存的指纹(SHA-256哈希)进行比较。即使攻击者获得了可信的CA证书或入侵了证书颁发机构,也无法执行MitM攻击——应用检查的是特定指纹,而不是CA链。这对于金融应用和包含敏感数据的应用尤其重要。
Certificate Pinning需要谨慎:当服务器上的证书更改时,所有旧版本的应用将无法连接。建议保存多个备用指纹(主用+备用),指定pin-set的到期日期,并通过标准CA验证实现回退机制。替代方案是首次使用时信任(TOFU),即应用在第一次连接时记住证书,并在证书更改时警告用户。根据OWASP(2026年),缺少Certificate Pinning位列移动应用三大漏洞之一(M3:不安全通信)。
在Alamofire 5+中,Certificate Pinning通过ServerTrustManager配合PinnedCertificatesTrustEvaluator(检查整个证书)或PublicKeysTrustEvaluator(仅检查公钥)进行配置。公钥更优——在相同CA更新证书时不会更改。使用[host: evaluator]字典创建ServerTrustManager,将其传递给Session并用于所有对受保护API的请求。
常见问题
SSL — 过时协议(2.0和3.0版本),因POODLE和BEAST漏洞而被认定为不安全。TLS — 其继任者,从TLS 1.0开始(RFC 2246,1999年)。任何现代的“SSL证书”都是TLS协议使用的X.509证书。SSL 3.0在所有现代操作系统和浏览器中已被禁止。
App Transport Security — Apple对应用安全性的要求。HTTP以明文形式传输数据,允许在公共Wi-Fi网络中截取令牌和用户的个人数据。ATS默认阻止HTTP和TLS低于1.2的HTTPS,即使没有开发者的操作也能保护用户。
使用SSL Labs(ssllabs.com/ssltest)或命令行:openssl s_client -tls1_3 -connect example.com:443。在大多数云平台(AWS CloudFront、Cloudflare、Nginx 1.19+、Caddy)上,TLS 1.3默认启用。在Android 10+上,支持已内置于系统提供商Conscrypt中。
Self-Signed Certificate — 由自己而非证书颁发机构签署的证书。不能在生产环境中使用——移动操作系统不信任此类证书。用于本地开发:通过MDM将证书添加到受信任列表中,或使用禁用验证的debug构建。
创建ServerTrustManager配合PinnedCertificatesTrustEvaluator或PublicKeysTrustEvaluator。前者检查整个证书,后者仅检查公钥(更优)。将管理器传递给Session(configuration: serverTrustManager:),并对所有向API发出的请求使用该会话。
总结
我们将开发一款交钥匙移动应用程序
IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。