访问HTTPS URL时遭遇TIC SSL Trust Error问题求助
解决iOS HTTPS请求的TIC SSL Trust Error问题
这个TIC SSL Trust Error 3:0我太熟了,本质就是iOS系统拒绝了你的HTTPS连接——原因很明确:你访问的是IP地址的HTTPS服务,而且服务器大概率用的是自签名证书。iOS默认只信任正规CA签发、域名匹配的SSL证书,这种IP+自签名的组合直接触发了安全拦截。
另外提一句:你用Data(contentsOf:)做同步网络请求其实不太推荐,它没有超时控制,错误处理也很受限,后面的方案我会换成更可靠的URLSession异步请求。
调试阶段临时解决(仅用于测试,绝对不能上线!)
如果只是本地调试想快速跑通,可以临时绕过SSL验证,但一定要用编译宏限制只在Debug环境生效,避免上线后出现安全漏洞:
DispatchQueue.global(qos: .background).async { let stringURL = "https://192.168.104.91:8443/update_info.xml" guard let url = URL(string: stringURL) else { print("无效的URL") return } // 自定义URLSession,设置代理处理SSL验证 let session = URLSession(configuration: .default, delegate: self, delegateQueue: nil) let task = session.dataTask(with: url) { data, response, error in if let error = error { print("请求失败:\(error.localizedDescription)") return } // 成功拿到数据后的处理逻辑 if let data = data { print("获取到数据,长度:\(data.count)") // 这里可以解析XML或者做其他操作 } } task.resume() } // 给你的ViewController添加URLSessionDelegate扩展 extension YourViewController: URLSessionDelegate { func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) { // 只在Debug环境绕过验证 #if DEBUG if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust, let serverTrust = challenge.protectionSpace.serverTrust { let credential = URLCredential(trust: serverTrust) completionHandler(.useCredential, credential) return } #endif // 非Debug环境走系统默认验证逻辑 completionHandler(.performDefaultHandling, nil) } }
生产环境的正确方案(必须这么做!)
上线的APP绝对不能绕过SSL验证,否则会被App Store拒绝,还存在安全风险,推荐两种合规方案:
方案1:使用正规SSL证书
给你的服务器申请一个绑定域名的正规SSL证书(比如Let's Encrypt的免费证书),然后改用域名访问(比如https://your-domain.com:8443/update_info.xml),这样iOS系统会自动信任证书,不需要任何额外代码。
方案2:将自签名证书加入APP信任列表
如果必须用自签名证书,把证书导入APP,然后在代码中验证服务器证书和本地证书一致:
- 准备证书文件:导出服务器的自签名证书为DER格式(后缀
.cer),拖入Xcode项目,确保勾选了你的APP Target。 - 实现证书验证逻辑:
extension YourViewController: URLSessionDelegate { func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) { // 只处理服务器信任验证 guard challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust, let serverTrust = challenge.protectionSpace.serverTrust else { completionHandler(.performDefaultHandling, nil) return } // 加载本地证书 guard let certPath = Bundle.main.path(forResource: "你的证书文件名", ofType: "cer"), let certData = try? Data(contentsOf: URL(fileURLWithPath: certPath)), let localCert = SecCertificateCreateWithData(nil, certData as CFData) else { completionHandler(.cancelAuthenticationChallenge, nil) return } // 配置信任策略:只信任本地的证书 let policies = [SecPolicyCreateSSL(true, challenge.protectionSpace.host as CFString)] SecTrustSetPolicies(serverTrust, policies as CFArray) SecTrustSetAnchorCertificates(serverTrust, [localCert] 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) } } }
内容的提问来源于stack exchange,提问作者Md. Mostafizur Rahman
相关产品推荐
相关产品推荐

