必须配置ssloptions +exportcertdata并配合sslverifyclient require及sslcacertificatefile,才能将客户端证书pem内容透传至后端环境变量ssl_client_cert。

要在 Apache 中启用客户端证书的完整 PEM 内容供后端(如 PHP、Python CGI)读取,关键就是正确配置 SSLOptions +ExportCertData。它本身不触发认证,只负责把已验证的客户端证书以环境变量形式透传过去,必须配合双向 SSL 认证整体流程才能生效。
确认双向认证基础已就位
+ExportCertData 只在客户端实际提供了有效证书并被 Apache 成功校验后才起作用。所以先确保以下配置存在且生效:
-
SSLVerifyClient require(或optional,但后端需自行处理空证书情况) -
SSLCACertificateFile或SSLCACertificatePath指向受信任的 CA 证书文件/目录 -
SSLVerifyDepth设置合理(通常 1–10,视证书链长度而定)
在正确的上下文中设置 SSLOptions
该指令必须放在启用 SSL 的虚拟主机内,且最好紧邻 SSLVerifyClient 配置,避免被覆盖:
- 写在
<virtualhost></virtualhost>块内部,不能只写在全局或<directory></directory>里(除非明确需要局部控制) - 推荐写法:
SSLOptions +StdEnvVars +ExportCertData(+StdEnvVars 提供基础协议/加密信息,+ExportCertData 补充证书内容) - 不要单独写
SSLOptions +ExportCertData,否则可能因缺少 StdEnvVars 导致后端收不到其他关键 SSL 环境变量
后端如何获取证书内容
启用后,Apache 会将客户端证书的完整 PEM 文本注入环境变量 SSL_CLIENT_CERT。例如在 PHP 中可直接读取:
if (isset($_SERVER['SSL_CLIENT_CERT'])) {
$certPem = $_SERVER['SSL_CLIENT_CERT'];
// 解析 PEM,提取 CN、OU、有效期等字段
}注意:该变量内容是原始换行符保留的 PEM 字符串(含 -----BEGIN CERTIFICATE-----),不是 Base64 编码后的单行值。
常见问题与检查点
-
重启 Apache 后仍收不到
SSL_CLIENT_CERT:先用curl -k --cert client.crt --key client.key https://yoursite/测试是否真有客户端证书提交;再检查 error_log 是否报 “No client certificate presented” 或 “unable to get local issuer certificate” -
PHP 中
$_SERVER为空:确认 PHP 运行模式(mod_php 一般支持;php-fpm 需额外配置passenv透传 SSL_* 变量) - 证书内容异常(乱码、截断):确认客户端证书为标准 PEM 格式,且未被代理或负载均衡提前终止 TLS











