Nginx需通过map指令从$ssl_client_s_dn提取CN、OU等结构化字段写入日志,避免正则匹配顺序依赖;须启用ssl_verify_client并配置CA证书;高精度场景推荐用ngx_lua解析ASN.1。

要让 Nginx 在日志中准确记录双向认证客户端证书的可识别身份(如 CN、OU 等),关键不是直接打印 $ssl_client_s_dn,而是从中提取结构化字段并稳定落库。因为 $ssl_client_s_dn 是一个逗号分隔的字符串(例如 CN=app-01,OU=Dev,O=Org,ST=Beijing,C=CN),其顺序不固定,正则匹配容易出错。
提取常用字段:CN 和 OU
使用 map 指令预处理 DN 字符串,定义可复用的变量:
map $ssl_client_s_dn $client_cn {
~CN=([^,]+) $1;
default "-";
}
<p>map $ssl_client_s_dn $client_ou {
~OU=([^,]+)(?:,|$) $1;
default "-";
}⚠️ 注意:~OU=([^,]+)(?:,|$) 这种写法比 ~OU=([^,]+)$ 更鲁棒,能匹配 OU 出现在中间或末尾的情况(如 OU=Dev,CN=app 或 CN=app,OU=Dev)。
在日志格式中引用提取结果
将提取出的变量加入 log_format,便于后端解析或审计:
log_format main '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'client_cn="$client_cn" client_ou="$client_ou" '
'ssl_verify="$ssl_client_verify"';这样每条访问日志会包含类似 client_cn="app-01" client_ou="Dev" 的字段,清晰标识调用方身份。
确保双向认证已启用且变量可用
只有在启用了客户端证书验证的前提下,$ssl_client_s_dn 才有值。相关配置必须存在:
-
ssl_client_certificate /etc/nginx/ssl/ca.crt;—— 指定信任的根 CA -
ssl_verify_client on;或optional;—— 否则变量为空字符串 -
ssl_verify_depth 2;—— 确保完整证书链被校验,DN 信息才可靠
进阶建议:需要更精确解析时用 Lua
当业务要求解析邮箱、UID、多值 OU 或处理含逗号的 DN 组件(如 CN=John\,Doe)时,正则不可靠。可借助 ngx_lua 模块做 ASN.1 解析:
- 安装
nginx-module-lua(OpenResty 自带) - 用
ssl.client.get_subject_name()获取结构化 table - 再 set 到自定义变量供 log_format 使用
这种方式绕过字符串解析风险,适合金融、政企等对身份字段准确性要求极高的场景。


















