Nginx启用mTLS需在server块中配置listen 443 ssl、ssl_certificate与key、ssl_client_certificate指向可信CA、ssl_verify_client on,并透传$ssl_client_verify和$ssl_client_s_dn至Java后端。

要在 Nginx + Java 应用的架构中启用 HTTPS 双向认证(mTLS),核心是让 Nginx 不仅验证自己身份(单向 TLS),还强制校验每个客户端提交的有效证书,并将可信身份信息透传给后端 Java 服务。这不是简单加几行配置就能生效,而是涉及证书体系、Nginx 指令语义、Java 端适配三个关键环节。
一、确认 Nginx 支持并准备可信 CA 证书
双向认证依赖 PKI 信任链,Nginx 必须能验证客户端证书是否由指定 CA 签发:
- 确保 Nginx 编译时启用了 --with-http_ssl_module(运行
nginx -V 2>&1 | grep ssl验证) - CA 证书文件(如
ca.crt)必须是标准 PEM 格式:以-----BEGIN CERTIFICATE-----开头,-----END CERTIFICATE-----结尾,不能含私钥、BOM 或多余空格 - 用命令快速校验:
openssl x509 -in ca.crt -text -noout能正常输出即格式正确;若报错unable to load certificate,大概率是换行符或不可见字符问题 - 该文件路径将用于
ssl_client_certificate指令,建议存为/etc/nginx/ssl/ca.crt并设权限600
二、Nginx server 块中启用强制双向校验
在监听 443 的 server 配置中,补充以下关键指令(注意不是 optional):
-
必须启用校验:
ssl_verify_client on;—— 这是强制开关,客户端不带证书或证书无效时直接返回400 Bad Request -
指定信任根:
ssl_client_certificate /etc/nginx/ssl/ca.crt;—— 路径必须与你生成客户端证书所用的 CA 完全一致(差一个空格或换行都会失败) -
禁止降级行为:不要写
optional或optional_no_ca,它们在生产环境等同于关闭安全校验 - 保留基础 HTTPS 配置:包括
ssl_certificate(服务端证书)、ssl_certificate_key(服务端私钥)、ssl_protocols TLSv1.2 TLSv1.3等
三、把客户端身份信息透传给 Java 后端
Nginx 默认只在校验层使用客户端证书,不会自动转发内容。Java 应用需通过 HTTP 头获取原始证书或解析后的字段:
Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。
立即学习“Java免费学习笔记(深入)”;
- 在
location /块中添加透传头:proxy_set_header X-Client-Verify $ssl_client_verify; proxy_set_header X-Client-DN $ssl_client_s_dn; proxy_set_header X-Client-CN $ssl_client_s_dn_cn; proxy_set_header X-SSL-Issuer $ssl_client_i_dn; proxy_set_header X-SSL-Client-Cert $ssl_client_cert;
-
$ssl_client_verify值为SUCCESS或FAILED,Java 可据此做前置拦截 -
$ssl_client_s_dn_cn是客户端证书中的 Common Name(如user@company.com),常用于身份映射 - 若需完整证书 PEM 内容(如供 Java 二次验签),用
$ssl_client_cert,但注意 Base64 编码和换行处理
四、Java 应用端配合要点
后端需识别并信任这些头,不能仅依赖 Nginx 校验结果:
- Spring Boot 示例:在 Filter 或 Controller 中检查
X-Client-Verify == "SUCCESS",再提取X-Client-CN做权限路由 - 若需复用证书做下游调用(如调第三方 mTLS 接口),可将
X-SSL-Client-Cert解析为X509Certificate对象 - 务必关闭 Java 自身的 HTTPS 重定向逻辑(如
server.forward-headers-strategy=framework),避免干扰 Nginx 透传的头 - 日志中记录
X-Client-DN便于审计溯源,不建议只存 CN,因 DN 更完整
整个流程不复杂但容易忽略细节:CA 文件格式、ssl_verify_client 的取值陷阱、头透传的变量名拼写、Java 端对空格和换行的处理。只要每一步都按 PKI 规范落地,就能真正实现企业级通信身份强绑定。

















