You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

iOS向带SSL证书服务器发起HTTPS请求遇连接失败问题求助

解决HTTPS请求出现TIC TCP Conn Failed (-65554)和HTTP load failed (-1003)的问题

嘿,我刚帮好几个开发者搞定过一模一样的问题,咱们一步步拆解排查:

先搞懂错误背后的原因

  • -65554:核心是SSL/TLS握手失败,要么是服务器证书不被系统信任,要么是ATS(App Transport Security)的安全规则拦截了连接
  • -1003:基本是伴随SSL错误出现的,意思是系统没法建立符合安全要求的HTTPS连接

最常见的解决方案:配置ATS(iOS 9+默认强制启用)

iOS从9.0开始默认开启ATS,要求所有HTTPS连接必须满足严格安全标准(比如TLS 1.2+、证书由可信CA颁发等)。如果你的服务器不符合这些标准,得在Info.plist里添加例外配置:

方案1:允许特定域名的非标准HTTPS连接(推荐,App Store审核更容易通过)

Info.plist中插入以下配置,把你的服务器域名替换成实际域名:

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSExceptionDomains</key>
    <dict>
        <key>你的服务器域名(比如example.com)</key>
        <dict>
            <key>NSIncludesSubdomains</key>
            <true/>
            <key>NSTemporaryExceptionMinimumTLSVersion</key>
            <string>TLSv1.0</string> <!-- 若服务器仅支持老版本TLS,按需修改 -->
            <key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
            <false/> <!-- 仅当服务器证书完全不可信时临时设为true,上线前务必改回 -->
        </dict>
    </dict>
</dict>

方案2:全局允许所有HTTP/HTTPS连接(仅测试环境用,不推荐上线)

如果只是临时测试,可以用这个配置,但上线前一定要换成方案1,否则App Store审核大概率被拒:

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
</dict>

如果是自签名/私有CA证书的问题

如果你的服务器用的是自签名证书,哪怕配置了ATS,系统还是会拒绝信任,这时候需要在代码里添加自定义信任逻辑:

  1. 让你的类遵守URLSessionDelegate协议
  2. 实现以下代理方法(注意:上线前一定要补充证书合法性验证,避免中间人攻击!):
func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
    guard let serverTrust = challenge.protectionSpace.serverTrust else {
        completionHandler(.cancelAuthenticationChallenge, nil)
        return
    }
    // 测试环境直接信任,上线前要替换成验证证书公钥/指纹的逻辑
    let credential = URLCredential(trust: serverTrust)
    completionHandler(.useCredential, credential)
}

最后检查你的URL是否合法

确保Constants.baseUrl + self.url拼接后是标准的HTTPS格式,比如https://api.example.com/user,没有拼写错误(比如少打了s、域名写错等)。

结合你的代码,修正后的请求示例大概是这样:

func doTask(completion: @escaping (_ dictionary: NSDictionary) -> Void) {
    self.start()
    guard let url = URL(string: Constants.baseUrl + self.url) else {
        // 处理URL无效的情况
        completion(NSDictionary())
        return
    }
    var request = URLRequest(url: url)
    // 按需添加请求头,比如Content-Type
    request.setValue("application/json", forHTTPHeaderField: "Content-Type")
    
    // 注意要设置delegate来处理证书信任(如果需要的话)
    let session = URLSession(configuration: .default, delegate: self, delegateQueue: nil)
    let task = session.dataTask(with: request) { data, response, error in
        if let error = error {
            print("请求错误:\(error)")
            completion(NSDictionary())
            return
        }
        // 解析数据并返回结果
        if let data = data, let dict = try? JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? NSDictionary {
            completion(dict)
        } else {
            completion(NSDictionary())
        }
    }
    task.resume()
}

内容的提问来源于stack exchange,提问作者D.Pacheco

火山引擎 最新活动