必须通过phpinfo()确认“Loaded Configuration File”路径才是真实生效的php.ini,修改后需重启Apache(非Restart),并验证openssl扩展启用顺序、extension_dir路径及openssl.cafile证书配置是否正确。

确认你改的是真正的 php.ini 文件
很多人在 XAMPP 控制面板里点“Config → PHP (php.ini)”打开的文件,根本不是 Apache 实际加载的那个。光靠这个路径去改 extension=openssl,十有八九白忙活。
正确做法是:在 htdocs 下建一个 info.php,内容为 <?php phpinfo(); ?>,浏览器访问 http://localhost/info.php,搜索 Loaded Configuration File —— 那一行显示的路径才是真实生效的 php.ini。
常见陷阱:
- XAMPP 8.2 和 8.3 共存时,实际加载的可能是
C:\xampp\php\php-8.3\php.ini,而非C:\xampp\php\php.ini - 用命令行跑
php -v或php --ini看到的路径,和 Apache 加载的未必一致(CLI 和 Web 模块可能读不同配置) - 改完没重启 Apache,扩展永远不加载
取消注释 openssl 扩展并注意加载顺序
打开真实的 php.ini,搜索 extension=openssl。如果它前面有分号(;extension=openssl),直接删掉分号即可。不要写成 extension=php_openssl.dll,XAMPP 的 extension_dir 已预设好路径,硬写 DLL 名称反而会失败。
立即学习“PHP免费学习笔记(深入)”;
关键点在于顺序:extension=openssl 必须出现在 extension=curl 之前。因为 cURL 在 HTTPS 场景下依赖 OpenSSL,若只开 cURL 不开 OpenSSL,curl_init() 可能静默返回 false,且无明确错误提示。
顺带检查 extension_dir 是否指向正确位置,例如:
extension_dir = "C:\xampp\php\ext"
确保该目录下存在 php_openssl.dll(Windows)或对应 SO 文件(Linux/macOS)。
解决 HTTPS 请求报 “unable to get local issuer certificate”
即使 openssl 扩展已启用,file_get_contents("https://...") 或 curl_exec() 仍可能报证书验证失败,典型错误是:
SSL certificate problem: unable to get local issuer certificate
这不是扩展没开,而是 PHP 不知道该信任哪些根证书。XAMPP 自带了 cacert.pem,但默认未启用。
在 php.ini 中添加或修改这一行(路径必须用正斜杠或双反斜杠):
openssl.cafile="C:/xampp/php/extras/ssl/cacert.pem"
或者更稳妥地,直接用绝对路径指向 XAMPP 自带的证书包(通常位于 C:\xampp\php\extras\ssl\cacert.pem)。改完务必重启 Apache。
验证方式:写个简单脚本运行 var_dump(openssl_get_cert_locations());,看输出里的 cafile 值是否与你设置的一致。
别忽略 OpenSSL 库本身的版本与兼容性
PHP 的 openssl 扩展能否真正支持 TLS 1.2+、ECDHE 密钥交换等现代特性,不仅取决于 PHP 配置,还取决于底层 libssl-1_1.dll(或 libssl-3.dll)是否够新、是否与 Apache 匹配。
常见问题:
- Apache 启动失败,错误日志出现
The specified module could not be found或0x000007e—— 很可能是 Apache 和 PHP 加载了 ABI 不兼容的 OpenSSL DLL - 用
php -r "print_r(openssl_get_cert_locations());"查到的库路径,和openssl.exe version -a显示的路径不一致,说明两边用了不同 OpenSSL
修复原则:Apache(xampp\apache\bin\)和 PHP(xampp\php\)目录下的 libssl-*.dll 与 libcrypto-*.dll 必须完全一致(同版本、同架构、同编译器 VC 版本),不能只换一个。
临时绕过证书验证(仅限开发测试)可在代码中加:
$ctx = stream_context_create(['http' => ['timeout' => 30], 'ssl' => ['verify_peer' => false, 'verify_peer_name' => false]]);
但生产环境绝对禁用——这等于关掉 HTTPS 的安全根基。



















