跳转到主内容
新派编程网 - 新潮编程理念,全新技术课堂!

如何利用 Nginx 提供的 $ssl_client_s_dn 提取客户端证书身份

Nginx 通过 $ssl_client_s_dn 获取客户端证书DN字符串,需启用mTLS并完成验证;配合 map 和正则可提取CN等字段,透传至后端需注意编码与日志调试。 Nginx 可以通过
$ssl_client_s_dn
变量获取客户端证书的可分辨名称(Subject Distinguished Name),前提是已启用双向 TLS(mTLS)并成功完成客户端证书验证。这个变量是字符串格式,包含类似
CN=alice,OU=dev,O=example.com
的内容,需进一步解析才能提取具体字段(如 CN、OU、O 等)。 确保客户端证书验证已启用 仅配置
ssl_client_certificate
和
ssl_verify_client
不足以让
$ssl_client_s_dn
生效;必须实际完成证书校验流程:
ssl_client_certificate /path/to/ca-bundle.crt;
—— 指定受信任的 CA 证书(用于验证客户端证书签名)
ssl_verify_client on | optional | optional_no_ca;
—— 推荐设为
on
强制验证;设为
optional
时,无证书请求仍继续,但变量为空
ssl_verify_depth 2;
—— 根据客户端证书链深度合理设置(通常 1 或 2) 直接使用 $ ssl _client_s_dn 传递身份信息 该变量在 SSL 握手完成后即可用,常用于透传给后端服务(如通过 HTTP Header):
proxy_set_header X-Client-DN $ssl_client_s_dn;
—— 后端可通过该 header 获取完整 DN 字符串
fastcgi_param SSL_CLIENT_S_DN $ssl_client_s_dn;
—— PHP-FPM 场景下注入 CGI 变量 注意:DN 中可能含逗号、等号、空格或特殊字符(如 UTF-8),若需 URL 安全传输,建议用
$ssl_client_s_dn_encoded
(Nginx 1.19.4+ 支持)或自定义 map 编码 提取特定字段(如 CN)需借助 map 指令解析 Nginx 原生不提供 DN 字段切分函数,但可通过正则 +
map
提取常用项。例如提取 CN: Nginx 在宝塔面板中轻松管理Nginx高性能Web服务器。提供可视化配置反向代理、负载均衡、SSL证书及HTTP缓存功能,一键优化高并发性能,助您高效搭建稳定、快速的网站运行环境。 下载
map $ssl_client_s_dn $client_cn { ~*CN=([^,;]+) $1; default ""; }
然后在 location 中使用:
proxy_set_header X-Client-CN $client_cn;
正则注意大小写(
~*
表示忽略大小写),匹配到第一个
CN=xxx
即止;多个 CN(极少见)只取首个 类似可定义
$client_ou
(
~*OU=([^,;]+)
)、
$client_o
(
~*O=([^,;]+)
)等 若 DN 含引号或转义(如
CN="Alice Doe"
),正则需增强:
~*CN=(?:"([^"]+)"|([^,;"\]+))
,并合并捕获组逻辑 调试与常见问题 开发阶段建议开启日志确认变量值是否正确生成: 在 log_format 中加入
$ssl_client_s_dn
或
$client_cn
,例如:
log_format main '$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" "$ssl_client_s_dn"';
若变量为空:检查证书是否被 CA 正确签名、客户端是否实际发送了证书、
ssl_verify_client
是否为
off
或握手失败 若字段提取为空:用 log 输出原始
$ssl_client_s_dn
,确认格式是否符合正则预期(如字段顺序、分隔符、大小写、是否存在引号) 注意:
$ssl_client_s_dn
仅在 HTTPS server block 及其子 location 中有效;HTTP 块中该变量始终为空

相关文章