必须启用ssl_verify_client on并完成mtls校验,再用$ssl_client_escaped_cert安全透传url编码后的证书,配合x-client-verify、x-client-dn等头传递状态与身份信息。

要让 Nginx 在代理 PHP-FPM 时透传客户端真实 SSL 证书,本质是把双向 TLS(mTLS)验证后的证书信息,安全、完整、可信地交给 PHP 应用处理。这不只是加几个 header,而是需同时满足:Nginx 成功完成客户端证书校验、正确编码证书内容、透传校验状态、且 PHP 能可靠解码和使用。
前提:必须启用并完成客户端证书验证
只有验证通过后,Nginx 的 SSL 变量才有效。缺一不可:
- ssl_verify_client on; —— 必须开启,不能用 optional
- ssl_client_certificate /path/to/ca-bundle.pem; —— 指向可信 CA 的 PEM 公钥文件(权限应为 644)
- ssl_certificate 和 ssl_certificate_key 已正确配置服务端证书
- Nginx 版本 ≥ 1.19.7(否则 $ssl_client_escaped_cert 不可用)
安全透传证书内容:用 URL 编码变量
原始证书含换行符、空格、特殊字符,直接用 $ssl_client_cert 会破坏 HTTP header。必须改用已 URL 编码的变量:
- 在 location ~ \.php(/|$) 块中添加:
proxy_set_header X-Client-Cert-Escaped $ssl_client_escaped_cert; - 该变量仅在校验成功时非空,无需额外判断
- PHP 中需解码:例如 urldecode($_SERVER['HTTP_X_CLIENT_CERT_ESCAPED'])(注意 HTTP_ 前缀和大写)
配套透传身份与校验结果
光传证书不够,后端还需快速知道“是否可信”“是谁”。建议一并设置:
- proxy_set_header X-Client-Verify $ssl_client_verify; —— 返回 SUCCESS/FAILED/NONE
- proxy_set_header X-Client-DN $ssl_client_s_dn; —— 主题名(已自动转义,相对安全)
- proxy_set_header X-Client-CN $ssl_client_s_dn_cn; —— 仅 CN 字段,轻量无换行,适合做用户标识
PHP 端使用注意事项
PHP 接收到的是字符串,不是原生证书对象。典型处理步骤:
- 先检查 $_SERVER['HTTP_X_CLIENT_VERIFY'] === 'SUCCESS'
- 对 $_SERVER['HTTP_X_CLIENT_CERT_ESCAPED'] 执行 urldecode()
- 用 openssl_x509_parse() 解析证书结构,提取 email、OU、serialNumber 等字段
- 避免直接信任 CN 或 DN,应结合业务逻辑做白名单或签发链校验
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











