Apache反向代理不原生透传SSL,而是通过SSL终止+X-Forwarded头或HTTPS后端转发实现上下文传递;需启用mod_ssl、mod_proxy等模块,并配置Java应用识别转发头。

Apache 在反向代理模式下本身不“透传 SSL”,而是通过配置决定是否将 HTTPS 请求以 HTTP 或 HTTPS 方式转发给后端 Java 应用(如 Tomcat、Spring Boot 内嵌容器)。所谓“SSL 透传”,实际是指让后端 Java 应用感知原始请求的加密上下文(如协议、端口、客户端证书等),而非 Apache 自己终止 SSL 后只发裸 HTTP。
关键前提:Apache 必须启用 mod_ssl 和 mod_proxy
确保已加载以下模块(通常在 httpd.conf 或 mods-enabled/ 中):
- mod_ssl.so —— 支持 HTTPS 接入
- mod_proxy.so —— 启用反向代理能力
- mod_proxy_http.so —— 转发 HTTP/HTTPS 请求
- (可选)mod_headers.so —— 用于添加或修改请求头
方案一:SSL 终止在 Apache(推荐,最常用)
Apache 解密 HTTPS 请求,再以 HTTP 协议转发给后端 Java 应用。此时需确保后端能正确识别原始协议(否则 Spring Security 可能误判为 HTTP,重定向回 http://)。
典型配置示例(VirtualHost 443):
<virtualhost>
ServerName example.com
SSLEngine on
SSLCertificateFile /path/to/cert.pem
SSLCertificateKeyFile /path/to/key.pem
<pre class="brush:php;toolbar:false;">ProxyPreserveHost On
ProxyRequests Off
# 将 / 路由到后端 HTTP 服务(如 Tomcat 的 8080)
ProxyPass / http://127.0.0.1:8080/
ProxyPassReverse / http://127.0.0.1:8080/
# 关键:告诉后端原始请求是 HTTPS
RequestHeader set X-Forwarded-Proto "https"
RequestHeader set X-Forwarded-Port "443"
Java 后端需配合处理这些头:
- Spring Boot:设置 server.forward-headers-strategy=framework(自动识别 X-Forwarded-*)
- Tomcat:在 server.xml 的
中添加:
protocol="HTTP/1.1" scheme="https" secure="true" proxyPort="443" proxyName="example.com" - 确保应用生成的重定向 URL、Cookie Secure 标志、HSTS 等行为符合 HTTPS 上下文
方案二:SSL 直通(SSL Passthrough)—— Apache 不支持原生实现
Apache 无法真正做 SSL passthrough(即不解析 TLS 握手、直接转发加密流),这是 L4 负载均衡器(如 HAProxy、Nginx Stream 模块、F5)的能力。
若强行模拟“透传”(例如用 mod_proxy_http 转发 HTTPS 到后端 HTTPS),本质仍是 SSL 终止 + 重建,不是真正的透传:
ProxyPass / https://127.0.0.1:8443/ # Apache 自己作为 TLS 客户端连接后端 ProxyPassReverse / https://127.0.0.1:8443/
这要求:
- 后端 Java 应用自身启用 HTTPS(如 Tomcat 配置了 SSL Connector)
- Apache 需信任后端证书(用 SSLProxyCACertificateFile 等配置)
- 性能开销翻倍(两次 TLS 握手与加解密)
- 客户端证书无法传递给后端(Apache 默认不转发 client cert)
客户端证书透传(进阶需求)
若需把用户浏览器的客户端证书信息传给 Java 后端,需显式提取并注入请求头:
SSLVerifyClient optional
SSLVerifyDepth 2
SSLOptions +StdEnvVars +ExportCertData
<h1>提取 PEM 格式客户端证书(如有)</h1><p>SSLUserName SSL_CLIENT_S_DN
RequestHeader set X-Client-Cert "%{SSL_CLIENT_CERT}s"
RequestHeader set X-Client-DN "%{SSL_CLIENT_S_DN}s"</p>
Java 应用可通过读取 X-Client-Cert 头获取 Base64 编码的证书内容,再解析验证。
不复杂但容易忽略的是头字段一致性与后端框架的信任配置。只要 Apache 正确设置 X-Forwarded-* 和必要证书头,并且 Java 应用主动启用对这些头的解析,就能可靠还原原始 HTTPS 上下文。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










