必须配置双向认证(mTLS)并设置SSLVerifyClient require、SSLCACertificateFile/Path,再在中启用SSLOptions +StdEnvVars +ExportCertData,PHP通过$_SERVER['SSL_CLIENT_CERT']读取PEM证书。

要在 Apache 中启用 SSLOptions +ExportCertData,让后端(如 PHP、CGI 或代理应用)能通过环境变量 SSL_CLIENT_CERT 读取客户端证书的 PEM 内容,关键不是“开启就行”,而是必须满足双向认证(mTLS)前提,并配合正确的 SSL 指令链。单独加这一项不会生效,还可能被忽略。
确认已启用客户端证书验证
+ExportCertData 只在客户端实际提供了有效证书时才注入环境变量。所以必须先配置强制验签:
- 设置
SSLVerifyClient require(或optional,但require更可靠) - 指定受信任的 CA 证书:用
SSLCACertificateFile或SSLCACertificatePath - 确保客户端访问时确实携带了由该 CA 签发的证书(浏览器或 curl 需显式指定)
在正确的上下文中设置 SSLOptions
该指令需放在启用了 SSL 的虚拟主机内,且位置要合理:
- 写在
<virtualhost></virtualhost>块中,紧邻SSLEngine on之后较稳妥 - 推荐写法:
SSLOptions +StdEnvVars +ExportCertData(+StdEnvVars通常需要一并开启,否则部分基础变量缺失) - 避免写在
<directory></directory>或<location></location>里——它不支持嵌套作用域继承,只对当前虚拟主机生效
后端如何读取证书内容
PHP 示例(其他语言类似,查对应环境变量 API):
-
$_SERVER['SSL_CLIENT_CERT']直接返回完整 PEM 字符串(含-----BEGIN CERTIFICATE-----头尾) - 注意:该变量仅在 TLS 握手成功且客户端证书被接受后存在;若为空,说明未触发验证或验证失败
- 调试建议:临时加一段 PHP 输出所有
SSL_*变量,确认SSL_CLIENT_VERIFY为SUCCESS,再看SSL_CLIENT_CERT
常见失效原因
即使配置语法正确,也可能拿不到证书数据:
- 浏览器未发送客户端证书(现代 Chrome/Firefox 默认隐藏该选项,需手动选择或用 curl 测试:
curl --cert client.crt --key client.key https://yoursite.com) - CA 证书路径错误或格式非法(PEM 编码,无 BOM,结尾有换行)
- Apache 版本过低或 OpenSSL 不支持(2.4.8+ 和 OpenSSL 1.0.2+ 均支持,但需确认 mod_ssl 已加载)
- 使用了
SSLProxyEngine场景——+ExportCertData对反向代理后端无效,它只影响 Apache 自身 CGI/PHP 环境


















