iOS Swift中如何信任带自签名SSL证书的端点?
解决自签名SSL证书端点访问失败的问题
我来帮你搞定这个问题——你遇到的是ATS(App Transport Security)的证书有效性校验问题,NSAllowsArbitraryLoads其实只是允许HTTP/HTTPS的任意加载,但并不会跳过SSL证书的合法性验证,所以才会继续报错。下面是具体的解决方案:
1. 完善Info.plist的ATS精准配置
不要只开全局的NSAllowsArbitraryLoads,针对你的目标域名做精准配置,既能解决问题,也能避免全局关闭ATS带来的安全风险。修改后的Info.plist配置如下:
<key>NSAppTransportSecurity</key> <dict> <key>NSExceptionDomains</key> <dict> <key>你的端点域名(比如example.com)</key> <dict> <key>NSIncludesSubdomains</key> <true/> <key>NSExceptionAllowsInsecureHTTPLoads</key> <true/> <key>NSExceptionRequiresForwardSecrecy</key> <false/> <key>NSExceptionAllowsInvalidCertificates</key> <true/> </dict> </dict> </key>
关键字段说明:
NSExceptionAllowsInvalidCertificates:这是核心配置,专门允许该域名的无效/自签名证书通过校验NSIncludesSubdomains:如果你的端点是子域名(比如api.example.com),设为true会覆盖所有子域名NSExceptionAllowsInsecureHTTPLoads:若端点是HTTP协议则需要开启,HTTPS协议可保留但非必须
2. 代码层面精准处理证书验证(可选更安全)
如果你不想完全放开域名的证书校验,或者需要只信任特定的自签名证书,可以在URLSession的代理方法里手动处理验证逻辑:
Swift 示例
class NetworkManager: NSObject, URLSessionDelegate { func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) { // 仅处理服务器信任挑战 guard challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust else { completionHandler(.performDefaultHandling, nil) return } // 直接信任该服务器证书(仅测试环境使用!) if let serverTrust = challenge.protectionSpace.serverTrust { let credential = URLCredential(trust: serverTrust) completionHandler(.useCredential, credential) } else { completionHandler(.performDefaultHandling, nil) } } // 使用带代理的URLSession发起请求 func sendRequest() { let session = URLSession(configuration: .default, delegate: self, delegateQueue: nil) let task = session.dataTask(with: URL(string: "你的端点完整URL")!) { data, response, error in // 处理请求结果 } task.resume() } }
Objective-C 示例
@interface NetworkManager : NSObject <NSURLSessionDelegate> @end @implementation NetworkManager - (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler { if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) { SecTrustRef serverTrust = challenge.protectionSpace.serverTrust; NSURLCredential *credential = [NSURLCredential credentialForTrust:serverTrust]; completionHandler(NSURLSessionAuthChallengeUseCredential, credential); } else { completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil); } } - (void)sendRequest { NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration]; NSURLSession *session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:nil]; NSURLSessionDataTask *task = [session dataTaskWithURL:[NSURL URLWithString:@"你的端点完整URL"] completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { // 处理请求结果 }]; [task resume]; } @end
重要提醒
- 以上配置仅适合测试环境,如果要发布到App Store,苹果会拒绝这种绕过证书校验的配置,正式环境务必使用合法的SSL证书
- 若有多个自签名证书的端点,可在
NSExceptionDomains中添加多个域名配置
内容的提问来源于stack exchange,提问作者Sagaya Abdul
相关产品推荐
相关产品推荐

