Swift实现HTTPS接口加密通讯

在使用 Alamofire 的 Session 实现无证书访问 HTTPS 接口时,如果要求抓包不是明文(即防止中间人攻击和抓包工具如 Charles/Fiddler 解密 HTTPS 流量),可以通过以下方式实现:


1. 使用 SSL Pinning(证书绑定)

SSL Pinning 是一种防止中间人攻击的技术,通过将服务器的公钥或证书嵌入客户端,确保客户端只与特定的服务器通信。

实现步骤:

  1. 获取服务器的证书
    从服务器获取 .cer.der 格式的证书文件,并将其添加到 Xcode 项目中。

  2. 配置 Alamofire 的 ServerTrustManagerServerTrustEvaluating
    使用 Alamofire 的 ServerTrustManagerServerTrustEvaluating 来实现 SSL Pinning。

    import Alamofire
    
    // 1. 加载证书
    let certificatePath = Bundle.main.path(forResource: "your_certificate", ofType: "cer")!
    let certificateData = try! Data(contentsOf: URL(fileURLWithPath: certificatePath))
    
    // 2. 创建 ServerTrustEvaluating
    let evaluator = PinnedCertificatesTrustEvaluator(certificates: [certificateData])
    
    // 3. 配置 ServerTrustManager
    let serverTrustManager = ServerTrustManager(evaluators: ["yourserver.com": evaluator])
    
    // 4. 创建 Session
    let session = Session(serverTrustManager: serverTrustManager)
    
    // 5. 发起请求
    session.request("https://yourserver.com/api").response { response in
        debugPrint(response)
    }
    
  3. 效果
    抓包工具(如 Charles)将无法解密 HTTPS 流量,因为客户端只信任绑定的证书。


2. 禁用明文传输(防止 HTTP 请求)

确保应用只使用 HTTPS,禁用 HTTP 请求。

实现步骤:

Info.plist 中添加以下配置:

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <false/>
    <key>NSExceptionDomains</key>
    <dict>
        <key>yourserver.com</key>
        <dict>
            <key>NSIncludesSubdomains</key>
            <true/>
            <key>NSExceptionAllowsInsecureHTTPLoads</key>
            <false/>
            <key>NSExceptionRequiresForwardSecrecy</key>
            <true/>
        </dict>
    </dict>
</dict>

3. 使用自定义的 URLSessionDelegate

如果需要更细粒度的控制,可以实现 URLSessionDelegateurlSession(_:didReceive:completionHandler:) 方法,手动验证服务器证书。

实现步骤:

import Alamofire

class CustomSessionDelegate: SessionDelegate {
    override func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
        // 验证服务器证书
        if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust {
            if let serverTrust = challenge.protectionSpace.serverTrust {
                // 自定义验证逻辑
                let credential = URLCredential(trust: serverTrust)
                completionHandler(.useCredential, credential)
                return
            }
        }
        completionHandler(.performDefaultHandling, nil)
    }
}

// 创建自定义 Session
let session = Session(delegate: CustomSessionDelegate())

// 发起请求
session.request("https://yourserver.com/api").response { response in
    debugPrint(response)
}

4. 防止抓包工具注入证书

抓包工具(如 Charles)通常会要求用户安装自定义根证书来解密 HTTPS 流量。可以通过以下方式防止抓包工具注入证书:

实现步骤:

  1. 检测设备是否安装了抓包工具的证书
    检查设备是否安装了 Charles/Fiddler 等工具的根证书。

    func isProxyEnabled() -> Bool {
        if let proxySettings = CFNetworkCopySystemProxySettings()?.takeRetainedValue() as? [String: Any],
           let httpProxy = proxySettings["HTTPProxy"] as? String, !httpProxy.isEmpty {
            return true
        }
        return false
    }
    
  2. 拒绝请求或提示用户
    如果检测到抓包工具,可以拒绝请求或提示用户关闭代理。


5. 使用双向 TLS(mTLS)

双向 TLS(mTLS)要求客户端和服务器都提供证书,进一步增加安全性。

实现步骤:

  1. 获取客户端证书
    从服务器获取客户端证书(.p12 文件)。

  2. 加载客户端证书
    在代码中加载客户端证书并配置 Alamofire。

    import Alamofire
    
    // 1. 加载客户端证书
    let certificatePath = Bundle.main.path(forResource: "client_certificate", ofType: "p12")!
    let certificateData = try! Data(contentsOf: URL(fileURLWithPath: certificatePath))
    
    // 2. 创建 URLCredential
    let credential = URLCredential(pkcs12: certificateData, password: "your_password")
    
    // 3. 创建 Session
    let session = Session()
    
    // 4. 发起请求
    session.request("https://yourserver.com/api")
        .authenticate(with: credential)
        .response { response in
            debugPrint(response)
        }
    

6. 总结

  • SSL Pinning 是最常用的防止抓包工具解密 HTTPS 流量的方法。
  • 禁用明文传输 确保应用只使用 HTTPS。
  • 自定义 URLSessionDelegate 提供更细粒度的控制。
  • 检测抓包工具 可以防止用户使用抓包工具。
  • 双向 TLS 提供更高的安全性,但实现复杂度较高。

根据你的需求选择合适的方法,通常 SSL Pinning 是最常用的解决方案。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容