怎样让php源码支持https请求_编译openssl与证书链配置【教程】

1次阅读

php httpS 请求失败主因是环境缺失或配置错位,需检查 Openssl/curl 扩展启用、证书路径正确及 CA 证书链有效,禁用证书验证仅限临时调试。

怎样让php源码支持https请求_编译openssl与证书链配置【教程】

PHP 默认支持 https 请求,但前提是底层 cURL 或 OpenSSL 扩展已正确编译并链接到可用的 OpenSSL 库,且运行时能加载可信 CA 证书链。问题往往不出在 PHP 代码本身(比如 file_get_contents('https://...')curl_exec()),而在于环境缺失或配置错位。

检查 PHP 是否已启用 OpenSSL 和 cURL 支持

直接运行 php -m | grep -E '^(openssl|curl)$'。若无输出,说明对应扩展未启用;若只有 curl 没有 openssl,cURL 可能是用系统自带的 NSS 或 GnuTLS 编译的,不支持标准 PEM 证书路径,也无法验证 HTTPS 证书链。

  • 确认 extension=opensslphp.ini 中未被注释,且 extension_dir 指向正确的 .so/.dll 路径
  • 运行 php -r "print_r(openssl_get_cert_locations());" 查看 PHP 认为的默认证书路径 —— 这个路径必须存在且包含有效的 CA bundle(如 ca-bundle.crtca-certificates.crt
  • 如果输出中 default_cert_file 是空或指向不存在的文件,后续 HTTPS 请求会因“unable to get local issuer certificate”失败

重新编译 PHP 以链接自建 OpenSSL(非必要勿动)

仅当系统 OpenSSL 版本过旧(如 centos 7 默认 1.0.2)、或需启用 FIPS/国密等特殊特性时,才需手动编译 OpenSSL 并让 PHP 链接它。多数现代发行版(ubuntu 22.04+、CentOS 8+)自带的 OpenSSL 1.1.1+ 已足够安全且兼容 PHP 7.4+ / 8.x。

  • 编译 OpenSSL 时加 --prefix=/usr/local/openssl,安装后确保 /usr/local/openssl/bin/openssl version 可执行
  • 编译 PHP 时指定 --with-openssl=/usr/local/openssl,而非 --with-openssl-dir(后者已被弃用)
  • 编译后运行 ldd $(php-config --extension-dir)/openssl.so | grep ssl,确认链接的是你刚装的 OpenSSL 库,而非系统旧版
  • 注意:PHP 8.2+ 不再支持 OpenSSL 1.0.x,强行链接会导致启动报错 undefined symbol: OPENSSL_sk_num

正确配置 CA 证书链(最常出问题的环节)

PHP 不读取系统级的 /etc/ssl/certs/ca-certificates.crt(除非你显式设置),也不自动从 curl.cainfoopenssl.cafile 加载 —— 它只认自己编译时硬编码的路径,或运行时通过 ini 配置覆盖。

立即学习PHP免费学习笔记(深入)”;

  • 下载最新 Mozilla CA bundle:curl -o /usr/local/share/ca-bundle.crt https://curl.se/ca/cacert.pem
  • php.ini 中添加两行:
    openssl.cafile=/usr/local/share/ca-bundle.crt
    curl.cainfo=/usr/local/share/ca-bundle.crt
  • 若使用 composer,还需设置环境变量 export COMPOSER_CAFILE=/usr/local/share/ca-bundle.crt,否则 composer install 仍可能失败
  • 重启 PHP-FPM 或 apache 后,再次运行 php -r "print_r(openssl_get_cert_locations());",确认 default_cert_file 已更新为你指定的路径

绕过证书验证不是解决方案

CURLOPT_SSL_VERIFYPEER => falsestream_context_create([... 'verify_peer' => false ...]) 会让 HTTPS 退化为明文 HTTP 级别安全性,且现代 PHP(8.0+)在 CLI 模式下对未验证连接会触发 E_WARNING,某些云环境甚至直接拒绝执行。

  • 临时调试可用,但上线前必须移除
  • 内网自签证书场景,应把内网 CA 的 PEM 文件追加到你的 ca-bundle.crt 末尾,而不是关验证
  • openssl.cafile 支持绝对路径,不支持相对路径或 ~ 符号;路径权限需确保 PHP 进程用户(如 www-data)可读

真正卡住人的从来不是“怎么编译”,而是编译完没改 php.ini,或者改了但没重启服务,又或者证书路径写错了一级目录——这些地方一错,file_get_contents('https://api.github.com') 就会静默返回 false,连错误信息都要开 error_reporting(E_ALL) 才看得见。

text=ZqhQzanResources