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

didReceiveAuthenticationChallenge多次调用及NSURLErrorDomainCode=-999问题咨询

问题描述

在基于React-Native-Webview开发的应用中,为网站实现SSL固定校验,通过didReceiveAuthenticationChallenge方法处理认证挑战时遇到以下异常:

  • 该方法被调用3次
  • 前两次调用能获取到相同的服务器证书,第三次调用时SecTrustGetCertificateAtIndex(serverTrust, 0)返回nil
  • 最终出现NSURLErrorDomainCode=-999错误

相关代码片段:

- (void)didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
                  completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * _Nullable))completionHandler
{
  SecTrustRef serverTrust = challenge.protectionSpace.serverTrust;
  SecCertificateRef certificate = SecTrustGetCertificateAtIndex(serverTrust, 0);
  // 后续校验逻辑...
}

服务器仅安装了用于比对的单张证书,疑问:此行为是否属于方法的正常表现?


解答

这种三次调用+第三次证书为空+返回-999错误的情况不属于正常行为,核心原因和解决方向如下:

  1. NSURLErrorDomainCode=-999的本质
    这个错误表示请求被主动取消,通常是前两次认证处理逻辑存在缺陷,导致Webview终止了后续请求流程。比如未正确调用completionHandler、错误地拒绝了合法认证等,都会触发该错误。

  2. 第三次调用时证书为空的可能原因

  • 认证挑战类型变更:前两次是服务器证书认证(NSURLAuthenticationMethodServerTrust),但第三次可能是其他类型的认证(比如客户端证书认证、HTTP Basic认证等),此时challenge.protectionSpace.serverTrust会为nil,自然无法获取到证书。
  • Webview的子请求触发:Webview加载页面时可能发起多个子请求(如静态资源、第三方脚本等),若某个子请求并非HTTPS协议,或者服务器返回的信任链异常,就会出现serverTrust无效的情况。
  • 代码未做空值校验:当前代码直接获取serverTrust和证书,未判断serverTrust是否为nil,当serverTrust无效时,SecTrustGetCertificateAtIndex必然返回nil。
  1. 修复建议
  • 先校验认证类型:在处理挑战前,先判断是否为服务器证书认证,非目标类型直接走默认处理:
    if (![challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
        completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil);
        return;
    }
    
  • 增加空值判断:确保serverTrust有效后再获取证书:
    SecTrustRef serverTrust = challenge.protectionSpace.serverTrust;
    if (!serverTrust || SecTrustGetCertificateCount(serverTrust) == 0) {
        completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil);
        return;
    }
    SecCertificateRef certificate = SecTrustGetCertificateAtIndex(serverTrust, 0);
    
  • 正确完成认证流程:证书校验通过后,必须调用completionHandler返回合法凭证;校验失败则明确拒绝,避免Webview因等待处理超时取消请求:
    // 假设校验通过
    if (证书校验逻辑通过) {
        NSURLCredential *credential = [NSURLCredential credentialForTrust:serverTrust];
        completionHandler(NSURLSessionAuthChallengeUseCredential, credential);
    } else {
        completionHandler(NSURLSessionAuthChallengeRejectProtectionSpace, nil);
    }
    
  • 排查第三次请求来源:通过challenge.protectionSpace.host查看第三次请求的目标地址,确认是否为预期内的HTTPS请求,排查是否存在非预期的子请求或重定向问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 04:55:17