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

自签名服务器证书验证遇SecTrustResultType.recoverableTrustFailure错误排查

问题分析与修复方案

你的代码存在几个关键问题,导致证书验证始终返回recoverableTrustFailure,以下是具体问题和修复后的代码:

核心错误点

  • 错误重建Trust对象:你直接提取服务器证书重新创建了Trust实例,但系统传入的trust已经包含完整的服务器证书链和默认的TLS策略,重新创建会丢失链的层级信息,无法正确验证证书链的完整性。
  • 未触发证书评估:SecTrustGetTrustResult只是获取已评估的结果,你没有主动调用评估方法(如SecTrustEvaluate)来完成验证流程。
  • 错误的结果处理:无论验证结果如何,你最后都调用completionHandler(false),直接拒绝连接。
  • 强制解包风险:caCertPath!这类强制解包会在证书文件缺失时导致崩溃,应该增加安全判断。

修复后的代码

func mqtt(_ mqtt: CocoaMQTT, didReceive trust: SecTrust, completionHandler: @escaping (Bool) -> Void) {
    // 安全获取CA证书路径与数据
    guard let caCertPath = Bundle.main.path(forResource: "ca", ofType: "der"),
          let caCertData = try? Data(contentsOf: URL(fileURLWithPath: caCertPath)),
          let caCert = SecCertificateCreateWithData(nil, caCertData as CFData) else {
        dprint("CA证书加载失败")
        completionHandler(false)
        return
    }
    
    // 使用系统传入的trust对象,而非重建
    var trustResult: SecTrustResultType = .invalid
    
    // 设置自定义锚点证书
    guard SecTrustSetAnchorCertificates(trust, [caCert] as CFArray) == errSecSuccess,
          SecTrustSetAnchorCertificatesOnly(trust, true) == errSecSuccess else {
        dprint("锚点证书设置失败")
        completionHandler(false)
        return
    }
    
    // 触发证书评估
    let evaluateStatus = SecTrustEvaluate(trust, &trustResult)
    
    // 处理评估结果
    var shouldProceed = false
    switch trustResult {
    case .proceed, .unspecified:
        dprint("证书验证通过")
        shouldProceed = true
    case .recoverableTrustFailure:
        dprint("可恢复的信任失败,通常是证书链问题或日期无效")
    case .deny, .fatalTrustFailure:
        dprint("证书验证被拒绝")
    case .invalid, .otherError:
        dprint("证书验证出错")
    @unknown default:
        dprint("未知验证结果")
    }
    
    // 根据评估结果决定是否允许连接
    completionHandler(shouldProceed)
}

额外说明

  • SecTrustSetAnchorCertificatesOnly(trust, true):设置只信任你指定的CA证书,避免系统默认信任锚干扰自签名证书的验证。
  • 优先使用系统传入的trust对象:它已经包含了服务器发送的完整证书链和适配当前连接的TLS策略,不需要手动重建。
  • 必须调用SecTrustEvaluate:这是触发证书验证流程的核心步骤,没有它SecTrustGetTrustResult只会返回初始的无效状态或旧结果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 14:55:19