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

iOS调用本地API遇NSURLErrorDomain Code=-1202证书无效问题求助

解决NSURLErrorDomain Code=-1202(自签名SSL证书信任问题)

你遇到的-1202错误是iOS系统默认拒绝信任自签名SSL证书导致的,系统认为此类连接存在安全风险。以下是针对你SwiftUI代码的两种解决方案:


方案一:开发环境临时处理(仅用于测试,禁止上线)

该方案跳过证书验证,仅适合本地开发测试,上线前必须移除,否则会被App Store审核拒绝。

代码修改步骤:

  1. 添加自定义证书信任代理类:
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)
    }
}
  1. 修改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审核要求。

操作步骤:

  1. 将你的自签名证书(.crt格式)添加到Xcode项目中,确保勾选对应的Target。
  2. 在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>
  1. 添加证书验证代理类:
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)
        }
    }
}
  1. 同方案一,在doHTTPUserCall中使用该代理创建URLSession即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 22:15:41