ssl单向认证只需配置ssl_cert_file和ssl_key_file,服务端提供证书供客户端验证;双向认证须启用ssl_verify_peer、指定ssl_cafile并确保客户端证书由对应ca签发,且需手动解析证书信息。

SSL单向认证在Swoole中只需配置server.crt和server.key
单向认证下,Swoole服务端只提供证书供客户端验证,不校验客户端身份。关键在于 ssl_cert_file 和 ssl_key_file 两个配置项必须正确指向服务器证书和私钥文件,且证书需由客户端信任的CA签发(或客户端显式信任自签名根证书)。
常见错误现象包括:SSL handshake failed、unable to get local issuer certificate,多因证书链不全、私钥密码未清除、或客户端未导入CA根证书导致。
使用场景:对外提供HTTPS API、Websocket服务等开放接口,例如 swoole_http_server 对接浏览器或通用HTTP客户端。
参数差异:ssl_client_cert_file 和 ssl_verify_peer 在单向模式下无需设置,设了也无效;ssl_verify_depth 默认为1,一般不用改。
SSL双向认证必须启用verify_peer并指定cafile
双向认证的核心判断依据是服务端主动要求并验证客户端证书。Swoole中需同时满足三个条件:ssl_verify_peer => true、ssl_cafile 指向可信CA根证书(或中间CA证书)、ssl_cert_file + ssl_key_file 仍需存在。
容易踩的坑:
-
ssl_verify_peer设为true但漏配ssl_cafile→ 握手直接失败,日志里可能只显示SSL error: unable to get issuer certificate - 客户端证书不是用
ssl_cafile中的CA签发的 → 验证失败,错误信息常含X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY - 服务端未在TLS握手阶段发送
CertificateRequest→ 客户端根本不会发证书,表现为连接卡在handshake,Wireshark可见ServerHello后无CertificateRequest消息
性能影响:每次新连接都会触发完整证书链验证,若CA根证书过大或验证逻辑复杂(如启用了CRL/OCSP),会增加握手延迟。生产环境建议关闭OCSP stapling(Swoole默认不支持),并确保 ssl_cafile 是精简后的PEM拼接体(仅含必要根+中间证书)。
Swoole 6.1.1 是一个专为 PHP 设计的高性能事件驱动并发网络引擎。作为稳定版,它修复了编译时对 zlib 依赖的缺失及 curl 模块的内存安全风险。该版本支持协程、多线程与多进程架构,内置 TCP/HTTP/WebSocket 服务器,能够显著提升 PHP 在微服务、实时通信等场景下的执行效率与并发能力。
客户端证书验证失败时Swoole不抛异常,而是静默断连
Swoole的SSL层在证书验证失败时不会触发PHP异常,也不会调用 onConnect 或 onReceive,连接会在握手阶段被底层SSL引擎直接关闭,表现就是客户端收不到任何响应,TCP连接快速RST。
调试建议:
- 开启Swoole日志:
log_level => SWOOLE_LOG_DEBUG,观察是否出现SSL verify failed类提示 - 用
openssl s_client -connect host:port -cert client.crt -key client.key -CAfile ca.crt手动测试,比代码调试更直观 - 确认客户端证书的
subjectAltName或commonName符合服务端验证策略(Swoole本身不校验域名,但OpenSSL底层可能因配置触发额外检查)
注意:Swoole 5.x 起默认使用系统OpenSSL,其行为受OpenSSL版本影响。例如 OpenSSL 3.0+ 对证书策略约束更严,可能拒绝缺少 extendedKeyUsage=clientAuth 的客户端证书。
双向认证下客户端证书内容无法直接在PHP层读取
Swoole不提供类似 $_SERVER['SSL_CLIENT_CERT'] 的变量。若业务需要提取客户端证书中的DN、序列号或SAN字段,必须在握手完成后主动调用OpenSSL函数解析。
实操路径:
- 在
onConnect回调中,用swoole_get_socket_from_fd($fd)获取原生socket资源 - 再通过
stream_context_get_options()或openssl_x509_parse()(需先用openssl_x509_read()从socket提取原始PEM)解析证书 - 注意:该过程必须在连接建立后立即做,不能等到
onReceive,因为证书信息只存在于TLS握手上下文中,后续数据帧里不携带
这个环节极易被忽略——很多开发者以为配置完 ssl_verify_peer 就自动能拿到证书信息,结果在业务逻辑里始终读不到 SSL_CLIENT_* 环境变量,本质是Swoole没做CGI式注入,得自己动手扒。









