You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS端Flutter应用配置自签名证书实现文件下载问题求助

Flutter iOS 端自签名证书 SSL 连接问题解决思路

针对你遇到的iOS端无法通过自签名证书建立SSL连接的问题,可从以下几个方向排查解决:

1. 修正ATS配置的证书固定策略

你当前使用的NSPinnedCAIdentities适用于信任CA签发的证书场景,但自签名证书本身属于叶子证书(无上层CA),改用NSPinnedLeafIdentities更合适。同时建议添加子域名包含配置,调整后的Info.plist配置如下:

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <false/>
    <key>NSPinnedDomains</key>
    <dict>
        <key>subdomain.domain.com</key>
        <dict>
            <key>NSPinnedLeafIdentities</key>
            <array>
                <dict>
                    <key>SPKI-SHA256-BASE64</key>
                    <string>+V2Jp3+Q27t23D7amlWpiIFQfx0TivlE6MjvpR7iLC4=</string>
                </dict>
            </array>
            <key>NSIncludesSubdomains</key>
            <true/>
        </dict>
    </dict>
</dict>

2. 重新验证SPKI哈希的生成过程

确保你生成哈希时使用的是正确的自签名根证书文件,并简化命令避免冗余步骤,重新生成的命令如下:

openssl x509 -in iotccpem -noout -pubkey | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | openssl base64

生成后对比原哈希值,若不一致说明之前的证书文件或命令步骤有误。

3. 针对Background Downloader库的原生层适配

由于该库可能未暴露badCertificateCallback,需在iOS原生代码中自定义URLSession的证书信任逻辑:

  1. 将iotccpem.pem证书文件添加到iOS项目的Bundle中(勾选「Copy items if needed」);
  2. 在AppDelegate.swift或SceneDelegate.swift中实现URLSession的证书验证代理方法:
func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
    guard let serverTrust = challenge.protectionSpace.serverTrust else {
        completionHandler(.cancelAuthenticationChallenge, nil)
        return
    }
    // 加载本地证书
    guard let certPath = Bundle.main.path(forResource: "iotccpem", ofType: "pem"),
          let certData = try? Data(contentsOf: URL(fileURLWithPath: certPath)),
          let cert = SecCertificateCreateWithData(nil, certData as CFData) else {
        completionHandler(.cancelAuthenticationChallenge, nil)
        return
    }
    // 将本地证书设为信任锚点
    SecTrustSetAnchorCertificates(serverTrust, [cert] as CFArray)
    SecTrustSetAnchorCertificatesOnly(serverTrust, true)
    // 验证信任链
    var trustResult: SecTrustResultType = .invalid
    SecTrustEvaluate(serverTrust, &trustResult)
    if trustResult == .unspecified || trustResult == .proceed {
        let credential = URLCredential(trust: serverTrust)
        completionHandler(.useCredential, credential)
    } else {
        completionHandler(.cancelAuthenticationChallenge, nil)
    }
}
  1. 若库支持自定义URLSessionConfiguration,将上述代理逻辑绑定到对应的Session中。

4. 验证本地证书格式有效性

用以下命令检查证书文件是否为合法的PEM格式:

openssl x509 -in iotccpem -text -noout

若命令能输出证书的详细信息(如有效期、公钥等),说明证书格式无问题;若报错需重新导出正确的PEM格式证书。

内容的提问来源于stack exchange,提问作者chrjs

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 19:40:40