要在Nginx层提取客户端证书序列号用于鉴权,核心是启用SSL双向认证并使用$ssl_client_serial变量(十六进制、大写、无分隔符),该变量仅在ssl_verify_client on且证书验证成功($ssl_client_verify为SUCCESS)时有效,可通过proxy_set_header传递给后端,需配合CA证书路径正确、权限充足及多维校验(如issuer或fingerprint)确保安全性。

要在 Nginx 层提取客户端证书序列号用于鉴权,核心是启用 SSL 客户端证书验证,并通过内置变量 $ssl_client_serial 获取序列号(十六进制、无分隔符、大写)。该变量仅在成功完成双向 TLS 握手后可用。
1. 配置 SSL 双向认证(mTLS)
确保 Nginx 启用了客户端证书校验,否则 $ssl_client_serial 始终为空:
- 设置
ssl_client_certificate指向受信任的 CA 证书(PEM 格式),用于验证客户端证书签名 - 启用
ssl_verify_client on(或optional,但鉴权场景建议on) - 确保
ssl_verify_depth足够(通常 1 或 2,取决于证书链长度)
2. 在 location 中安全使用 $ssl_client_serial
该变量仅在 SSL 握手成功且证书有效时才非空。建议配合 $ssl_client_verify 判断有效性:
-
$ssl_client_verify值为SUCCESS表示证书被 CA 正确签发且未过期/吊销 - 若为
FAILED:xxx或NONE,不应信任$ssl_client_serial - 可在
if ($ssl_client_verify != SUCCESS) { return 403; }提前拦截无效请求
3. 传递序列号给后端服务
常用方式是注入 HTTP 请求头,供上游应用鉴权:
- 使用
proxy_set_header X-Client-Cert-Serial $ssl_client_serial; - 注意:序列号是纯十六进制字符串(如 A1B2C3D4E5F67890),不含
:或前缀,可直接入库或比对 - 如需格式化(例如转小写、加冒号分隔),需借助 Lua(via lua-nginx-module)或外部服务,Nginx 原生不支持字符串转换
4. 注意事项与常见问题
避免因配置疏漏导致鉴权失效或误判:
- CA 证书文件路径必须正确,且 Nginx 主进程有读取权限;证书内容不能包含多余空格或乱码
-
$ssl_client_serial不代表客户端身份唯一性——不同 CA 签发的证书可能有相同序列号,务必结合$ssl_client_issuer或证书指纹($ssl_client_fingerprint)增强校验 - 若使用
ssl_verify_client optional,需显式检查$ssl_client_verify,否则未带证书的请求也会进入后续逻辑 - 日志中可临时添加
$ssl_client_serial:$ssl_client_verify辅助调试,上线后移除以防敏感信息泄露


















