workerman 4 的异步 httpclient 访问 https 站点时,若证书失效(过期、链不完整、域名不匹配或根证书不受信),openssl 会强制拒绝连接;生产环境严禁禁用证书验证,应通过指定 cafile 路径加载可信 ca 证书,开发调试可临时关闭校验但须严格限制环境。

Workerman 4 的异步 HttpClient(基于 ReactPHP 或自研协程 HTTP 客户端)在访问外部 HTTPS 站点时,若对方证书失效(如过期、链不完整、域名不匹配),默认会直接拒绝连接,抛出类似 SSL certificate problem: certificate has expired 或 unable to get local issuer certificate 的错误。这不是 Workerman 的 Bug,而是底层 OpenSSL 对 TLS 握手安全性的强制校验。
证书失效的常见类型与对应表现
先确认你遇到的是哪一类问题,再针对性处理:
-
证书已过期:日志中出现
certificate has expired或ERR_CERT_DATE_INVALID;OpenSSL 检查显示notAfter时间早于当前时间(2026年10月3日) -
证书链不完整:目标站点只返回服务器证书,没发中间 CA;OpenSSL 输出中
Verify return code: 20,且showcerts只显示一段 PEM -
域名不匹配:用 IP 或测试域名访问,但证书 SAN 中不含该值;报错含
RemoteCertificateNameMismatch或ERR_CERT_COMMON_NAME_INVALID -
根证书不受信:对方用私有 CA 或老旧 CA(如 WoSign、StartCom)签发;
Verify return code: 2,或 SSL Labs 显示 “Chain issues: Incomplete”
生产环境安全处理原则
Workerman 4 的异步请求走的是 PHP 的 stream_context_create 或底层 OpenSSL,**不能也不应全局禁用证书验证**(如设 verify_peer => false)。正确做法是:
- 对已知不可控的第三方服务(如某些老政企 API),单独配置可信 CA 证书路径,而非关闭校验
- 将对方提供的根证书或中间证书(PEM 格式)保存到项目
certs/目录,例如certs/payment-ca.pem - 在发起请求时显式传入:
'ssl' => ['cafile' => __DIR__ . '/certs/payment-ca.pem'] - 若使用
Workerman\Http\Client(v4.1+),可构造带自定义上下文的 Client 实例,复用该 CA 配置
快速定位与验证方法
别只看 Workerman 日志——它往往只报“connection failed”。你需要从外部复现握手过程:
- 在部署机器上运行:
openssl s_client -connect api.legacy-gov.cn:443 -servername api.legacy-gov.cn -showcerts -verify 5 - 观察输出末尾的
Verify return code和证书段数量 - 用 SSL Labs 输入对方域名,看 “Certificate Chain” 是否标红
- 若确认是对方问题,联系其运维补全证书链或更新证书;同步在你这边配置 fallback 逻辑(如降级调用 HTTP 备用接口,仅限非敏感场景)
开发调试临时绕过(仅限本地)
仅限开发机或内网测试环境,且必须加明确注释和开关控制:
- 在 stream context 中加入:
'ssl' => ['verify_peer' => false, 'verify_peer_name' => false, 'allow_self_signed' => true] - 切勿提交到 Git,更不可出现在生产构建中
- 建议用环境变量控制,例如:
if (getenv('APP_ENV') === 'local') { $context['ssl']['verify_peer'] = false; }











