iOS调用本地API遇NSURLErrorDomain Code=-1202证书无效问题求助
解决NSURLErrorDomain Code=-1202(自签名SSL证书信任问题)
你遇到的-1202错误是iOS系统默认拒绝信任自签名SSL证书导致的,系统认为此类连接存在安全风险。以下是针对你SwiftUI代码的两种解决方案:
方案一:开发环境临时处理(仅用于测试,禁止上线)
该方案跳过证书验证,仅适合本地开发测试,上线前必须移除,否则会被App Store审核拒绝。
代码修改步骤:
- 添加自定义证书信任代理类:
class SelfSignedCertDelegate: NSObject, 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 // 默认行为:拒绝未知证书 completionHandler(.performDefaultHandling, nil) } }
- 修改
doHTTPUserCall方法,替换默认URLSession为自定义实例:
func doHTTPUserCall() async { var url = "https://192.168.179.185:8090/CC0001/BE/admin/api/v1/employee/deviceid/" url += deviceId guard let reqUrl = URL(string: url) else { print("Invalid URL") return } var req = URLRequest(url: reqUrl) req.httpMethod = "GET" let formatter = DateFormatter() formatter.dateFormat = "yyyy-MM-dd" formatter.timeZone = TimeZone(abbreviation: "ETC") // 使用自定义Session let session = URLSession(configuration: .default, delegate: SelfSignedCertDelegate(), delegateQueue: nil) // 改用async/await替代回调,更符合SwiftUI异步逻辑 do { let (data, response) = try await session.data(for: req) if let httpResponse = response as? HTTPURLResponse { print("Response HTTP Status code: \(httpResponse.statusCode)") } let decoder = JSONDecoder() decoder.dateDecodingStrategy = .formatted(formatter) users = try decoder.decode([User].self, from: data) } catch { print("HTTP Request Failed \(error)") } }
方案二:生产环境合规方案(推荐)
通过导入自签名证书并验证的方式,确保连接安全,符合App Store审核要求。
操作步骤:
- 将你的自签名证书(
.crt格式)添加到Xcode项目中,确保勾选对应的Target。 - 在
Info.plist中添加App Transport Security配置:
<key>NSAppTransportSecurity</key> <dict> <key>NSExceptionDomains</key> <dict> <key>192.168.179.185</key> <dict> <key>NSIncludesSubdomains</key> <true/> <key>NSExceptionRequiresForwardSecrecy</key> <false/> </dict> </dict> </dict>
- 添加证书验证代理类:
class CustomCertDelegate: NSObject, 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: "your-cert-filename", ofType: "crt"), 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) } } }
- 同方案一,在
doHTTPUserCall中使用该代理创建URLSession即可。
内容的提问来源于stack exchange,提问作者Pjaks
相关产品推荐
相关产品推荐

