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

iOS端Swift连接SignalR遇自签名证书协商错误的解决方法

解决iOS 11 Swift SignalR客户端连接自签名证书服务器的问题

你遇到的Error during negotiation request确实大概率是iOS默认拒绝信任自签名证书导致的——iOS的ATS(App Transport Security)会阻止未受信任的HTTPS请求,而SignalR的协商阶段需要正常的HTTP/HTTPS通信才能完成。下面是针对iOS 11 Swift环境的具体解决方案:

步骤1:配置Info.plist的ATS例外

首先需要在项目的Info.plist中添加ATS配置,允许你的服务器域名跳过严格的证书验证:

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSExceptionDomains</key>
    <dict>
        <key>services.test.com</key>
        <dict>
            <key>NSIncludesSubdomains</key>
            <true/>
            <key>NSExceptionAllowsInsecureHTTPLoads</key>
            <true/>
            <key>NSExceptionRequiresForwardSecrecy</key>
            <false/>
        </dict>
    </dict>
</dict>

注意:如果你的服务器是HTTPS协议,NSExceptionAllowsInsecureHTTPLoads设为true是允许跳过证书验证;如果是HTTP,这一步是允许非HTTPS请求(不过生产环境不建议用HTTP)。

步骤2:给SignalR客户端配置自定义URLSession(信任自签名证书)

SignalR-Swift库允许自定义URLSession,我们可以通过实现URLSessionDelegate来手动信任自签名证书。修改你的代码如下:

首先,添加一个自定义的URLSessionDelegate类:

class CustomURLSessionDelegate: NSObject, URLSessionDelegate {
    func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
        // 信任自签名证书
        if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust {
            guard let serverTrust = challenge.protectionSpace.serverTrust else {
                completionHandler(.cancelAuthenticationChallenge, nil)
                return
            }
            let credential = URLCredential(trust: serverTrust)
            completionHandler(.useCredential, credential)
        } else {
            completionHandler(.performDefaultHandling, nil)
        }
    }
}

然后修改你的test()函数,给SignalR连接配置这个自定义的URLSession:

func test() {
    // 初始化自定义Delegate和URLSession
    let sessionDelegate = CustomURLSessionDelegate()
    let sessionConfiguration = URLSessionConfiguration.default
    let urlSession = URLSession(configuration: sessionConfiguration, delegate: sessionDelegate, delegateQueue: nil)
    
    // 创建SignalR连接(注意如果是HTTPS,这里要改成https://services.test.com/signalr)
    let persistentConnection = SignalR("https://services.test.com/signalr", connectionType: .persistent)
    // 给SignalR连接设置自定义URLSession
    persistentConnection.urlSession = urlSession
    
    let simpleHub1 = Hub("testHub")
    persistentConnection.useWKWebView = false
    persistentConnection.addHub(simpleHub1)
    
    // 以下是你的原有回调逻辑,修复了重复设置connected的问题
    persistentConnection.received = { data in
        print(data)
    }
    persistentConnection.starting = {
        print("Starting...")
    }
    persistentConnection.reconnecting = {
        print("Reconnecting...")
    }
    persistentConnection.connected = { [weak self] in
        guard let self = self else { return }
        print("Connected. Connection ID: \(String(describing: persistentConnection.connectionID))")
    }
    persistentConnection.reconnected = { [weak self] in
        guard let self = self else { return }
        print("Reconnected. Connection ID: \(String(describing: persistentConnection.connectionID))")
    }
    persistentConnection.disconnected = {
        print("Disconnected.")
    }
    persistentConnection.connectionSlow = {
        print("Connection slow...")
    }
    persistentConnection.error = { error in
        print("Error occurred: \(error ?? "Unknown error")")
        persistentConnection.start()
    }
    
    persistentConnection.start()
}

关键说明

  • 我注意到你的代码里重复设置了persistentConnection.connected回调,这会覆盖之前的逻辑,所以合并成了一个,避免冲突。
  • 如果你的服务器确实是HTTP协议,那主要问题可能不是证书,但还是建议切换到HTTPS;如果是HTTPS,一定要把连接地址改成https://开头。
  • 自定义Delegate里的逻辑是信任所有服务器证书,只建议在测试环境使用,生产环境应该使用合法的CA签发证书,或者添加特定自签名证书到信任列表(更安全的做法)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:45:58