需要具有 Spring 安全性的 HTTPS 支持反向代理
Require HTTPS with Spring Security behind a reverse proxy
我有一个 Spring MVC 应用程序受 Spring 安全保护。大多数应用程序使用简单的 HTTP 来节省资源,但小部分处理更多机密信息并需要 HTTPS 通道。
摘自 security-config.xml
:
<sec:http authentication-manager-ref="authenticationManager" ... >
...
<sec:intercept-url pattern="/sec/**" requires-channel="https"/>
<sec:intercept-url pattern="/**" requires-channel="http"/>
</sec:http>
一切正常,直到我们决定将其迁移到主服务器,那里的应用程序服务器 运行 在反向代理后面。现在 HTTPS 由反向代理处理,应用程序服务器只能看到 HTTP 请求,并且不允许访问 /sec/**
层次结构。
经过一些研究,我发现代理添加了一个 X-Forwarded-Proto: https
header (*),但是在 Spring 安全 HttpServletRequest.isSecure()
用于确定提供的通道安全性(摘自SecureChannelProcessor
javadoc)。
我如何告诉 Spring 安全 X-Forwarded-Proto: https
header 足以满足安全请求?
我知道我可以报告关于代理配置的部分,但是代理管理员真的不喜欢那个解决方案,因为代理背后有很多应用程序,配置可能会增长到无法管理的状态。
我目前使用 Spring Security 3.2 和 XML 配置,但我准备接受基于 Java 配置 and/or 更新版本的答案。
(*) 当然,如果 header 出现在传入请求中,代理会删除它,因此应用程序可以放心它.
如果您的站点是 HTTPS 并且您 运行 Apache Tomcat 位于另一个处理 TLS 终止的系统后面,您可以告诉 Tomcat 到 "pretend" 它正在处理TLS 终止。
这使得 request.isSecure()
return true
;
为此,您需要将 secure="true"
添加到 server.xml
中的连接器配置。
https://tomcat.apache.org/tomcat-7.0-doc/config/http.html
另请参阅 scheme
属性。
类似于 NeilMcGuigan 的回答,表明解决方案是 servlet 容器端。
Tomcat 更好。有一个 valve 专用于 masking 反向代理的副作用。 Remote IP Valve 的 Tomcat 文档摘录:
这个阀门的另一个特点是用代理或负载均衡器通过请求 header(例如 "X-Forwarded-Proto")。
阀门配置示例:
<Valve className="org.apache.catalina.valves.RemoteIpValve"
internalProxies="192\.168\.0\.10|192\.168\.0\.11"
remoteIpHeader="x-forwarded-for" proxiesHeader="x-forwarded-by"
protocolHeader="x-forwarded-proto" />
这样 应用程序本身没有其他配置,如果请求包含 header,对 Request.isSecure()
的调用将 return 为真] X-Forwarded-Proto=https
的字段。
我想到了另外两种可能性,但最终更喜欢那个:
- 使用在 Spring 安全性
ChannelProcessingFilter
之前激活的过滤器以 HttpServletRequestWrapper
覆盖 isSecure()
来包装请求以处理 X-Forwarded-Proto
header - 需要编写和测试过滤器和包装器
- 使用Spring
BeanPostProcessor
寻找ChannelProcessingFilter
并手动注入ChannelDecisionManager
可以考虑X-Forwarded-Proto
header-水平真的太低了
Spring 引导使其变得非常简单(至少对于嵌入式 Tomcat)。
1.将以下行添加到您的 application.properties:
server.forward-headers-strategy=native
server.tomcat.remote-ip-header=x-forwarded-for
server.tomcat.protocol-header=x-forwarded-proto
2。使用您的 HttpSecurity
配置执行以下技巧。
// final HttpSecurity http = ...
// Probably it will be in your `WebSecurityConfigurerAdapter.configure()`
http.requiresChannel()
.anyRequest().requiresSecure()
来源是Spring引导参考指南
84.3 Enable HTTPS When Running behind a Proxy Server
另请检查下面的答案以获得
我有一个 Spring MVC 应用程序受 Spring 安全保护。大多数应用程序使用简单的 HTTP 来节省资源,但小部分处理更多机密信息并需要 HTTPS 通道。
摘自 security-config.xml
:
<sec:http authentication-manager-ref="authenticationManager" ... >
...
<sec:intercept-url pattern="/sec/**" requires-channel="https"/>
<sec:intercept-url pattern="/**" requires-channel="http"/>
</sec:http>
一切正常,直到我们决定将其迁移到主服务器,那里的应用程序服务器 运行 在反向代理后面。现在 HTTPS 由反向代理处理,应用程序服务器只能看到 HTTP 请求,并且不允许访问 /sec/**
层次结构。
经过一些研究,我发现代理添加了一个 X-Forwarded-Proto: https
header (*),但是在 Spring 安全 HttpServletRequest.isSecure()
用于确定提供的通道安全性(摘自SecureChannelProcessor
javadoc)。
我如何告诉 Spring 安全 X-Forwarded-Proto: https
header 足以满足安全请求?
我知道我可以报告关于代理配置的部分,但是代理管理员真的不喜欢那个解决方案,因为代理背后有很多应用程序,配置可能会增长到无法管理的状态。
我目前使用 Spring Security 3.2 和 XML 配置,但我准备接受基于 Java 配置 and/or 更新版本的答案。
(*) 当然,如果 header 出现在传入请求中,代理会删除它,因此应用程序可以放心它.
如果您的站点是 HTTPS 并且您 运行 Apache Tomcat 位于另一个处理 TLS 终止的系统后面,您可以告诉 Tomcat 到 "pretend" 它正在处理TLS 终止。
这使得 request.isSecure()
return true
;
为此,您需要将 secure="true"
添加到 server.xml
中的连接器配置。
https://tomcat.apache.org/tomcat-7.0-doc/config/http.html
另请参阅 scheme
属性。
类似于 NeilMcGuigan 的回答,表明解决方案是 servlet 容器端。
Tomcat 更好。有一个 valve 专用于 masking 反向代理的副作用。 Remote IP Valve 的 Tomcat 文档摘录:
这个阀门的另一个特点是用代理或负载均衡器通过请求 header(例如 "X-Forwarded-Proto")。
阀门配置示例:
<Valve className="org.apache.catalina.valves.RemoteIpValve"
internalProxies="192\.168\.0\.10|192\.168\.0\.11"
remoteIpHeader="x-forwarded-for" proxiesHeader="x-forwarded-by"
protocolHeader="x-forwarded-proto" />
这样 应用程序本身没有其他配置,如果请求包含 header,对 Request.isSecure()
的调用将 return 为真] X-Forwarded-Proto=https
的字段。
我想到了另外两种可能性,但最终更喜欢那个:
- 使用在 Spring 安全性
ChannelProcessingFilter
之前激活的过滤器以HttpServletRequestWrapper
覆盖isSecure()
来包装请求以处理X-Forwarded-Proto
header - 需要编写和测试过滤器和包装器 - 使用Spring
BeanPostProcessor
寻找ChannelProcessingFilter
并手动注入ChannelDecisionManager
可以考虑X-Forwarded-Proto
header-水平真的太低了
Spring 引导使其变得非常简单(至少对于嵌入式 Tomcat)。
1.将以下行添加到您的 application.properties:
server.forward-headers-strategy=native
server.tomcat.remote-ip-header=x-forwarded-for
server.tomcat.protocol-header=x-forwarded-proto
2。使用您的 HttpSecurity
配置执行以下技巧。
// final HttpSecurity http = ...
// Probably it will be in your `WebSecurityConfigurerAdapter.configure()`
http.requiresChannel()
.anyRequest().requiresSecure()
来源是Spring引导参考指南
84.3 Enable HTTPS When Running behind a Proxy Server
另请检查下面的答案以获得