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

Swift 5 下如何为Starscream 4.0.4的WebSocket配置SSL证书实现安全通信

问题解答

1 无自定义证书配置也能正常连接的原因

你当前使用的FoundationSecurity(allowSelfSigned: true)配置会直接信任所有自签名证书,不会校验服务端返回的证书是否为你自行生成的对应证书,因此无需导入自定义证书即可完成连接。
你当前的服务端仅配置了单向SSL认证,仅要求客户端信任服务端证书即可建立连接,因此任何开启了自签名证书信任的客户端都能接入服务,这就是你担心的安全隐患的来源。

2 Starscream 4.x版本配置服务端证书钉住的方法

4.x版本废弃了旧的security属性,统一通过CertPinner相关类完成证书配置,操作步骤如下:

  1. 首先将你生成的pem格式证书转换为Xcode可识别的cer格式,执行以下命令:
    openssl x509 -outform der -in cert.pem -out cert.cer
  2. 将生成的cert.cer文件导入Xcode项目,确保勾选了对应应用的Target成员资格
  3. 初始化WebSocket时传入自定义证书完成钉住配置,代码示例如下:
var request = URLRequest(url: URL(string: "wss://mydomain.com:1234")!)
request.timeoutInterval = 10
// 加载项目内的自定义证书
guard let certPath = Bundle.main.path(forResource: "cert", ofType: "cer"),
      let certData = try? Data(contentsOf: URL(fileURLWithPath: certPath)) else {
    fatalError("证书加载失败")
}
// 初始化pinner时指定仅信任传入的自定义自签名证书
let pinner = FoundationSecurity(certs: [certData], allowSelfSigned: true)
socket = WebSocket(request: request, certPinner: pinner)
socket?.delegate = self
socket?.connect()

完成该配置后,客户端只会和持有对应证书的服务端建立连接,可有效避免中间人攻击。

3 实现仅你的应用可连接服务的方案

要实现只有携带对应证书的应用可访问服务,需要配置双向TLS认证,即服务端也会校验客户端的证书有效性,无有效证书的连接会被直接拒绝,配置步骤如下:

3.1 后端服务配置

修改node.js的https服务初始化参数,开启客户端证书校验:

const httpsServer = https.createServer(
{
    key: fs.readFileSync('./certs/key.pem'),
    cert: fs.readFileSync('./certs/cert.pem'),
    // 开启客户端证书校验
    requestCert: true,
    // 配置信任的CA证书,此处为你自行生成的自签名证书
    ca: [fs.readFileSync('./certs/cert.pem')],
    // 直接拒绝无有效证书的请求
    rejectUnauthorized: true
});

httpsServer.listen(1234, function() 
{
    logger.log.info(filename + "Server is listening on port " + 1234);
});

var wsServer = new webSocketServer({
    httpServer: httpsServer,
    autoAcceptConnections: false
});

3.2 客户端配置

首先将你的证书和密钥打包为PKCS12格式的客户端证书,执行以下命令,导出时按提示设置密码:
openssl pkcs12 -export -out client.p12 -inkey key.pem -in cert.pem
将生成的client.p12导入Xcode项目,修改Swift端初始化代码,传入客户端证书:

var request = URLRequest(url: URL(string: "wss://mydomain.com:1234")!)
request.timeoutInterval = 10
// 加载服务端证书用于钉住校验
guard let certPath = Bundle.main.path(forResource: "cert", ofType: "cer"),
      let certData = try? Data(contentsOf: URL(fileURLWithPath: certPath)),
      // 加载客户端证书用于服务端校验
      let p12Path = Bundle.main.path(forResource: "client", ofType: "p12"),
      let p12Data = try? Data(contentsOf: URL(fileURLWithPath: p12Path)) else {
    fatalError("证书加载失败")
}
let p12 = FoundationSecurity.PKCS12(data: p12Data, password: "你导出p12时设置的密码")
let pinner = FoundationSecurity(
    certs: [certData],
    allowSelfSigned: true,
    pkcs12: p12
)
socket = WebSocket(request: request, certPinner: pinner)
socket?.delegate = self
socket?.connect()

完成以上配置后,只有携带对应客户端证书的应用才能成功和服务端建立连接。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 12:09:04