PHP连接WebSocket时SSL证书错误的直接原因是stream_context_create()默认启用证书校验,而服务端使用自签名、过期证书或CA不在PHP信任链中;开发环境可临时禁用verify_peer和verify_peer_name,生产环境必须配置有效证书或cafile路径。

PHP 连接 WebSocket 时提示 SSL certificate problem
直接原因是 stream_context_create() 默认启用证书校验,而服务端用的是自签名证书、过期证书,或 CA 不在 PHP 的信任链里。常见报错:SSL operation failed with code 1. OpenSSL Error messages: error:1416F086:SSL routines:tls_process_server_certificate:certificate verify failed。
解决思路不是“关掉校验就完事”,得看场景:开发环境可临时跳过,生产环境必须用有效证书或正确配置 CA 路径。
- 开发调试时,加
verify_peer => false和verify_peer_name => false即可绕过(仅限可信内网) - 生产环境必须设
cafile指向正确的 PEM 格式根证书(如/etc/ssl/certs/ca-certificates.crt或自签 CA 的 .pem 文件) - 若服务端证书是通配符或含 SAN,确保
peer_name设置为实际连接的域名(如wss://api.example.com),否则verify_peer_name会失败
使用 stream_socket_client() 连 wss:// 时 context 参数怎么写
PHP 原生不支持 wss:// 协议名直连,必须用 ssl:// + 端口 443,并手动处理 WebSocket 握手。关键在 stream_context_create() 的 SSL 选项。
正确写法示例(开发环境):
立即学习“PHP免费学习笔记(深入)”;
$context = stream_context_create([
'ssl' => [
'verify_peer' => false,
'verify_peer_name' => false,
'allow_self_signed' => true,
]
]);
$fp = stream_socket_client('ssl://echo.websocket.org:443', $errno, $errstr, 30, STREAM_CLIENT_CONNECT, $context);
注意:allow_self_signed 必须配合 verify_peer => false 才生效;单独设 allow_self_signed => true 但 verify_peer => true 仍会失败。
cURL 不能直接连 WebSocket,别被误导
很多搜索结果建议用 curl_init('wss://...'),这是无效的。cURL 不支持 WebSocket 协议升级(Upgrade: websocket),它只做 HTTP(S) 请求,无法维持长连接或处理二进制帧。
真要用 cURL,只能模拟握手请求(发 GET + Sec-WebSocket-Key 头),然后靠 fread/fwrite 手动读写原始 socket —— 这等于自己实现 WebSocket 客户端,成本远高于用 stream_socket_client 或现成库(如 ratchet/pawl)。
- 别在
curl_setopt里加CURLOPT_SSL_VERIFYPEER => false试图“修复 wss 连接”,它根本不会走到那步 - 如果只是想测试 wss 服务是否可达,用
openssl s_client -connect host:443 -servername domain.com更直接
用 Ratchet/Pawl 时证书错误怎么处理
ratchet/pawl 底层还是调 stream_socket_client,证书控制点在 Connector 构造时传入的 array $options。
示例(跳过校验):
$connector = new Connector(Loop::get(), [
'tls' => [
'verify_peer' => false,
'verify_peer_name' => false,
'allow_self_signed' => true,
]
]);
注意:tls 键名不能写成 ssl,Pawl 会识别 tls 并透传给底层 context;漏掉 verify_peer_name 可能导致连接成功但握手被拒绝(服务端校验 SNI 失败)。
证书问题最常被忽略的一点:PHP 进程启动后才加载 CA 包,如果运行中更新了系统证书(如 update-ca-certificates),必须重启 PHP-FPM 或 CLI 进程,否则新证书不生效。











