我尝试使用 spring security xml 中的以下配置访问 CloudFoundry 上的应用程序
<intercept-url pattern="/signup*" access="permitAll" requires-channel="https" />
但它给了我错误这个网页有一个重定向循环
但是,当我将其更改为时,requires-channel="http"
我可以正常看到我的页面。在这两种情况下,我都https
在我的应用程序中使用了。这是预期的行为吗?
我尝试使用 spring security xml 中的以下配置访问 CloudFoundry 上的应用程序
<intercept-url pattern="/signup*" access="permitAll" requires-channel="https" />
但它给了我错误这个网页有一个重定向循环
但是,当我将其更改为时,requires-channel="http"
我可以正常看到我的页面。在这两种情况下,我都https
在我的应用程序中使用了。这是预期的行为吗?
首先,退后一步,这(https://johnpfield.wordpress.com/2014/09/10/configuring-ssltls-for-cloud-foundry/)为问题的性质提供了极好的上下文。
关键段落是
“这里的威胁模型是云的入口点是高可用性、安全的代理服务器。一旦流量穿过该边界,它就位于受信任的子网上。事实上,运行 Tomcat 应用程序服务器的实际 IP 地址和端口号在云之外是不可见的。获得对该端口的 HTTP 请求的唯一方法是通过安全代理。这种模式是安全架构从业者中公认的最佳实践。”</p>
因此,我们可能不希望或不需要 SSL,但请继续阅读以了解在使用 Cloud Foundry 上部署的 Spring Security 时如何避免 https 重定向问题。
您将在 Cloud Foundry 安装的边界处拥有负载均衡器、HAProxy 或某种终止 SSL 的代理。作为惯例,无论您使用什么,都应配置为设置 X-Forwarded-For 和 X-Forwarded-Proto 标头。请求标头“X-Forwarded-Proto”包含值 http 或 https,具体取决于原始请求,您需要使用此标头参数在堆栈中进一步做出安全决策。
最干净的方法是在容器级别,因此 Spring Security 的行为与部署容器无关。一些典型的配置选项如下
Tomcat 应配置为 RemoteIPValve,如此处所述
好消息是 Cloud Foundry 的 Java buildpack 已经为您完成了这项工作,如此处所示
由于 Tomcat 是嵌入的,Java buildpack 中的 Tomcat 配置不会被激活(参见 buildpack检测标准),因此需要一些内部 Spring Boot 配置。幸运的是,按照您对 Spring Boot 的期望进行配置非常简单,您可以按照此处的说明打开 Tomcat 的 RemoteIPValve ,只需定义
server.tomcat.remote_ip_header=x-forwarded-for
server.tomcat.protocol_header=x-forwarded-proto
这两种方法都会导致 Tomcat 阀覆盖 ServletRequest.isSecure() 行为的相同结果,因此应用程序不知道任何代理的使用。请注意,阀门仅在设置了“X-Forwarded-Proto”标题时使用。
或者,如果你真的想进入低级别,你可以深入研究 Spring Security 的核心,如此处所示。作为这项工作的一部分,关于如何通过 Servlet API 为其他容器(WebLogic、JBoss、Jetty、Glassfish)提供“X-Forwarded-Proto”标头,在https://的评论中分享了一些有用的发现github.com/BroadleafCommerce/BroadleafCommerce/issues/424
作为附加说明,CloudFlare 还可以充当终止 SSL 的反向代理(这是通过此处讨论的 PWS 推荐的方法),它确实转发了相关的标头。
https://stackoverflow.com/a/28300485/752167
http://experts.hybris.com/answers/33612/view.html
https://github.com/cloudfoundry/java-buildpack/commit/540633bc932299ef4335fde16d4069349c66062e
https://support.run.pivotal.io/entries/24898367-Spring-security-with-https
当我尝试使用 Spring Security 使用 HTTPS 保护我的页面时,我遇到了同样的问题。
从 CloudFoundry Support 的讨论来看,他们似乎“在路由器上终止 SSL 连接”。请参阅“是否可以通过 SSL (HTTPS) 访问我的应用程序? ”。
一年多之后,我找不到关于这个问题的更多信息。
万一它仍然有用......我发现这篇文章提供了解决类似问题的线索。
问题是 org.springframework.security.web.access.channel.SecureChannelProcessor bean 使用 ServletRequest.isSecure() 来决定是接受连接还是重定向,这在云内部变得混乱。
对该 bean 的以下覆盖似乎在 BlueMix 下完成了这项工作 - 不确定 $WSSC 请求标头是否适用于所有环境。
@Component
public class ChannelProcessorsPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessAfterInitialization(final Object bean, final String beanName) throws BeansException {
if (bean instanceof SecureChannelProcessor) {
final SecureChannelProcessor scp = (SecureChannelProcessor) bean;
return new ChannelProcessor() {
@Override
public void decide(FilterInvocation invocation,
Collection<ConfigAttribute> config) throws IOException,
ServletException {
HttpServletRequest httpRequest = invocation.getHttpRequest();
// Running under BlueMix (CloudFoundry in general?), the
// invocation.getHttpRequest().isSecure() in SecureChannelProcessor
// was always returning false
if ("https".equals(httpRequest.getHeader("$WSSC"))) {
return;
}
scp.decide(invocation, config);
}
@Override
public boolean supports(ConfigAttribute attribute) {
return scp.supports(attribute);
}
};
}
return bean;
}
@Override
public Object postProcessBeforeInitialization(final Object bean, final String beanName) throws BeansException {
return bean;
}
}