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

如何使用PHP读取TLS证书并实现安全WebSocket连接?

解决PHP安全WebSocket证书加载失败的问题

看起来你遇到的核心问题是证书文件格式不匹配PHP的要求,再加上代码里混用了流资源和普通socket函数,导致一系列报错。我来一步步帮你解决:

一、先理清证书文件的问题

你提供的cert-0x8zHR文件里混合了证书请求(CSR)、私钥、域名证书和中间证书,PHP在读取时会被多余的CSR内容干扰,导致无法正确识别私钥。咱们先整理出正确的证书文件:

  1. 提取私钥:从cert-0x8zHR里复制从-----BEGIN PRIVATE KEY-----到-----END PRIVATE KEY-----的全部内容(包括首尾行),保存为example.com.key文件。
  2. 整理证书链:
    • 从cert-0x8zHR里复制第一个-----BEGIN CERTIFICATE-----到-----END CERTIFICATE-----的内容(这是你的域名证书);
    • 把cert-Du9H8N里的中间证书内容追加到上面的内容后面;
    • 保存为example.com.crt文件(顺序必须是:域名证书在前,中间证书在后)。

验证证书和私钥是否匹配:用以下命令检查,两个输出的MD5值必须一致

openssl x509 -noout -modulus -in example.com.crt | openssl md5
openssl rsa -noout -modulus -in example.com.key | openssl md5

二、修正PHP代码的两处关键错误

错误1:混用流资源和普通Socket函数

stream_socket_accept()返回的是流资源,不能用socket_read()/socket_write()/socket_close()这些普通socket函数,要换成对应的流操作函数fread()/fwrite()/fclose()。这也是你后续收到socket_read() expects parameter 1 to be resource报错的原因之一。

错误2:SSL配置优化

针对Let's Encrypt证书,调整SSL选项,确保PHP能正确加载证书:

$context = stream_context_create();
// Let's Encrypt是可信CA,verify_peer设为true没问题,测试阶段可以临时设为false排查
stream_context_set_option($context, 'ssl', 'verify_peer', true);
stream_context_set_option($context, 'ssl', 'verify_peer_name', true);
stream_context_set_option($context, 'ssl', 'allow_self_signed', false);
stream_context_set_option($context, 'ssl', 'peer_name', 'example.com');
stream_context_set_option($context, 'ssl', 'CN_match', 'example.com');
stream_context_set_option($context, 'ssl', 'SNI_enabled', true);
// 指定整理好的证书链和私钥文件
stream_context_set_option($context, 'ssl', 'local_cert', '/path/to/example.com.crt');
stream_context_set_option($context, 'ssl', 'local_pk', '/path/to/example.com.key');
// 如果私钥设置了密码,需要添加下面这行(Let's Encrypt默认无密码)
// stream_context_set_option($context, 'ssl', 'passphrase', 'your_key_password');

三、修正后的完整PHP示例代码

$context = stream_context_create();
stream_context_set_option($context, 'ssl', 'allow_self_signed', false);
stream_context_set_option($context, 'ssl', 'verify_peer', true);
stream_context_set_option($context, 'ssl', 'verify_peer_name', true);
stream_context_set_option($context, 'ssl', 'peer_name', 'example.com');
stream_context_set_option($context, 'ssl', 'CN_match', 'example.com');
stream_context_set_option($context, 'ssl', 'SNI_enabled', true);
stream_context_set_option($context, 'ssl', 'local_cert', '/path/to/example.com.crt');
stream_context_set_option($context, 'ssl', 'local_pk', '/path/to/example.com.key');

$serverSocket = stream_socket_server(
    'tls://example.com:8090',
    $errNo,
    $errStr,
    STREAM_SERVER_BIND | STREAM_SERVER_LISTEN,
    $context
);

if (!$serverSocket) {
    die("启动服务器失败: $errStr ($errNo)");
}

echo "安全WebSocket服务器运行在 wss://example.com:8090\n";

while (true) {
    $client = stream_socket_accept($serverSocket);
    if (!$client) {
        echo "接受客户端连接失败\n";
        continue;
    }

    // 读取握手请求
    $request = fread($client, 5000);
    if (!$request) {
        fclose($client);
        continue;
    }

    // 提取WebSocket密钥
    if (!preg_match('#Sec-WebSocket-Key: (.*)\r\n#', $request, $matches)) {
        fclose($client);
        continue;
    }

    $key = base64_encode(pack('H*', sha1($matches[1] . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11')));
    $headers = "HTTP/1.1 101 Switching Protocols\r\n";
    $headers .= "Upgrade: websocket\r\n";
    $headers .= "Connection: Upgrade\r\n";
    $headers .= "Sec-WebSocket-Version: 13\r\n";
    $headers .= "Sec-WebSocket-Accept: $key\r\n\r\n";

    // 发送握手响应
    fwrite($client, $headers);

    // 示例:给客户端发送消息(注意WebSocket需要正确的帧格式)
    $response = "Hello from secure WebSocket!";
    $frame = chr(0x81) . chr(strlen($response)) . $response;
    fwrite($client, $frame);

    // 关闭连接
    fclose($client);
}

fclose($serverSocket);

最后检查事项

  1. 确保证书和私钥文件的权限正确,PHP进程有读取权限(比如设置为640,属主为www-data或PHP运行的用户);
  2. 客户端连接时,确保host变量是example.com,端口是8090,并且服务器的8090端口已经开放(防火墙/安全组要放行);
  3. 如果还是报错,可以临时把verify_peer和verify_peer_name设为false,排除证书验证的问题,再逐步排查。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 07:17:51