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

非安全SSL证书HTTPS服务器的调用限制及iOS与浏览器访问差异问题

解析iOS NSURLSession与浏览器访问非安全SSL证书服务器的差异,以及如何限制此类调用

嘿,我来帮你理清这个问题的来龙去脉,还有对应的解决办法:

首先,为什么浏览器和NSURLSession的表现不一样?
浏览器对SSL证书的校验非常严格——只要证书是自签名、过期、域名不匹配这类非受信任的情况,就会直接弹出隐私错误,不让你轻易访问(除非你手动添加例外)。但iOS的NSURLSession呢?默认情况下,当遇到非安全证书时,它会触发服务器信任挑战(就是你看到的那条challenge : <NSURLProtectionSpace: 0x60000000e050>: Host:ucsmv2012.xx.xxxxx.com, Server:https, Auth-Scheme:NSURLAuthenticationMethodServerTrust, Realm:(null), Port:7002, Proxy:NO, Proxy-Type:(null)警告),但如果你的代码没有专门处理这个挑战,系统可能会默认“放行”,所以请求能返回200状态码,但那条警告就是在告诉你:“这个证书不安全,我其实是破例允许的”。

接下来,怎么实现你要的「限制Web服务调用」,也就是让NSURLSession拒绝非安全证书?
你需要通过NSURLSession的代理方法,手动处理服务器信任挑战,只接受合法的证书,拒绝非安全的。具体步骤如下:

1. 给NSURLSession设置代理

创建session的时候指定代理对象(记得让你的类遵守NSURLSessionDelegate协议):

// Swift示例
let session = URLSession(configuration: .default, delegate: self, delegateQueue: nil)
// Objective-C示例
NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:nil];

2. 实现代理方法处理信任挑战

在你的代理类里实现didReceiveChallenge方法,严格校验证书:

func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
    // 只处理服务器信任类型的挑战
    guard challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust else {
        completionHandler(.performDefaultHandling, nil)
        return
    }
    
    // 获取服务器信任对象
    guard let serverTrust = challenge.protectionSpace.serverTrust else {
        // 无法获取信任对象,直接取消请求
        completionHandler(.cancelAuthenticationChallenge, nil)
        return
    }
    
    // 用系统默认规则校验证书合法性
    let isTrusted = SecTrustEvaluateWithError(serverTrust, nil)
    
    if isTrusted {
        // 证书合法,允许继续连接
        let credential = URLCredential(trust: serverTrust)
        completionHandler(.useCredential, credential)
    } else {
        // 证书不合法,拒绝连接——这就实现了限制调用的需求
        completionHandler(.cancelAuthenticationChallenge, nil)
    }
}

Objective-C版本:

- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * _Nullable credential))completionHandler {
    if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
        SecTrustRef serverTrust = challenge.protectionSpace.serverTrust;
        NSError *error = nil;
        BOOL isTrusted = SecTrustEvaluateWithError(serverTrust, &error);
        
        if (isTrusted) {
            NSURLCredential *credential = [NSURLCredential credentialForTrust:serverTrust];
            completionHandler(NSURLSessionAuthChallengeUseCredential, credential);
        } else {
            // 拒绝非安全证书,取消请求
            completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil);
        }
    } else {
        completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil);
    }
}

额外提醒

  • 如果你之前没实现这个代理方法,系统的默认行为在不同iOS版本可能有差异,有些版本会默认接受自签名证书,导致请求成功但留下警告。
  • 当你拒绝非安全证书后,NSURLSession会取消请求,你可以在URLSession:task:didCompleteWithError:代理方法里捕获这个错误,给用户提示“服务器证书不安全,无法访问”之类的信息。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 08:23:36