插件窝 干货文章 Nginx服务器和iOS的HTTPS安全通信怎么配置

Nginx服务器和iOS的HTTPS安全通信怎么配置

证书 Nginx serverTrust completionHandle 381    来源:    2025-04-21

Nginx服务器与iOS应用的HTTPS安全通信配置指南

一、Nginx服务器HTTPS配置

1. 获取SSL证书

  • 从权威CA机构(如Let's Encrypt、DigiCert等)获取证书
  • 或使用OpenSSL生成自签名证书(仅用于测试环境)
# 生成自签名证书示例
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/nginx/ssl/nginx.key -out /etc/nginx/ssl/nginx.crt

2. Nginx配置HTTPS

server {
    listen 443 ssl;
    server_name yourdomain.com;

    ssl_certificate /etc/nginx/ssl/nginx.crt;
    ssl_certificate_key /etc/nginx/ssl/nginx.key;

    # 启用TLS 1.2/1.3,禁用不安全的协议
    ssl_protocols TLSv1.2 TLSv1.3;

    # 配置安全的加密套件
    ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305';
    ssl_prefer_server_ciphers on;

    # 启用HSTS
    add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";

    # 其他配置...
    location / {
        # 你的应用配置
    }
}

3. 强制HTTP跳转HTTPS(可选)

server {
    listen 80;
    server_name yourdomain.com;
    return 301 https://$host$request_uri;
}

二、iOS应用配置

1. 配置ATS(App Transport Security)

在Info.plist中添加ATS配置:

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <false/>
    <key>NSExceptionDomains</key>
    <dict>
        <key>yourdomain.com</key>
        <dict>
            <key>NSIncludesSubdomains</key>
            <true/>
            <key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
            <false/>
            <key>NSTemporaryExceptionMinimumTLSVersion</key>
            <string>TLSv1.2</string>
            <key>NSTemporaryExceptionRequiresForwardSecrecy</key>
            <true/>
        </dict>
    </dict>
</dict>

2. 证书验证处理

使用系统信任的证书(推荐)

  • 确保你的证书由受信任的CA签发
  • iOS默认会验证这些证书

自定义证书验证(自签名证书)

func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {

    guard let serverTrust = challenge.protectionSpace.serverTrust else {
        completionHandler(.cancelAuthenticationChallenge, nil)
        return
    }

    // 1. 设置策略
    let policies = NSMutableArray()
    policies.add(SecPolicyCreateSSL(true, challenge.protectionSpace.host as CFString))
    SecTrustSetPolicies(serverTrust, policies)

    // 2. 验证服务器证书
    var error: CFError?
    if SecTrustEvaluateWithError(serverTrust, &error) {
        // 验证成功
        let credential = URLCredential(trust: serverTrust)
        completionHandler(.useCredential, credential)
    } else {
        // 验证失败
        completionHandler(.cancelAuthenticationChallenge, nil)
    }
}

3. 证书固定(可选增强安全)

// 预先计算证书的公钥哈希
let pinnedKeys = ["sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="]

func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {

    guard challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust,
          let serverTrust = challenge.protectionSpace.serverTrust else {
        completionHandler(.cancelAuthenticationChallenge, nil)
        return
    }

    // 验证证书链
    var secResult = SecTrustResultType.invalid
    let status = SecTrustEvaluate(serverTrust, &secResult)

    if status == errSecSuccess,
       (secResult == .proceed || secResult == .unspecified),
       let serverCertificate = SecTrustGetCertificateAtIndex(serverTrust, 0) {

        // 获取服务器证书的公钥
        if let serverPublicKey = SecCertificateCopyKey(serverCertificate),
           let serverPublicKeyData = SecKeyCopyExternalRepresentation(serverPublicKey, nil) as Data? {

            let keyHash = serverPublicKeyData.sha256().base64EncodedString()
            if pinnedKeys.contains("sha256/\(keyHash)") {
                // 公钥匹配
                completionHandler(.useCredential, URLCredential(trust: serverTrust))
                return
            }
        }
    }

    // 验证失败
    completionHandler(.cancelAuthenticationChallenge, nil)
}

三、测试与验证

  1. 服务器测试工具:

    • openssl s_client -connect yourdomain.com:443 -servername yourdomain.com
    • SSL Labs测试: https://www.ssllabs.com/ssltest/
  2. iOS端测试:

    • 使用Charles或Wireshark抓包验证加密情况
    • 测试在不同网络环境下的连接稳定性

四、常见问题解决

  1. 证书不受信任错误:

    • 确保iOS设备信任你的CA
    • 对于自签名证书,需要在设备上手动安装并信任证书
  2. TLS版本不匹配:

    • 确保Nginx和iOS都支持相同的TLS版本(推荐TLS 1.2+)
  3. ATS阻止连接:

    • 检查Info.plist中的ATS配置
    • 确保服务器使用强加密套件
  4. 证书过期问题:

    • 设置证书过期提醒
    • 考虑使用自动续期工具(如Certbot)

通过以上配置,你可以建立Nginx服务器与iOS应用之间安全的HTTPS通信通道,保护数据传输的安全性。