使用Spring Security将https卸载到负载均衡器

时间:2011-11-03 21:42:33

标签: jsp spring-mvc https spring-security load-balancing

现在,负载均衡器处理https,然后将该https传递给我的Web服务器。因此,为每个请求处理https double。我想要做的是完全卸载https,这样我的网络服务器就不必处理它了。

如果Web服务器认为所有请求都是http,我如何配置Spring Security和JSP页面?显然,我必须修改配置的<intercept-url>元素,使其requires-channel属性始终为httpany。在我的JSP页面中,我必须在<c:url value=''/>${secureUrl}之前添加${nonSecureUrl}个链接,具体取决于结果页面是否需要为https或http。控制器的重定向也需要像这样修改......还有别的吗?

修改JSP页面中的所有链接以包含方案和主机似乎非常痛苦。有没有更好的方法呢?

3 个答案:

答案 0 :(得分:6)

如果您在负载均衡器处终止SSL,则负载均衡器应发送一个标头,指示最初请求的协议。例如,F5添加了X-Forwarded-Proto。

从这里,您可以创建自定义ChannelProcessor来查看此标题,而不是查看request.isSecure()。然后,您可以继续使用<intercept-url requires-channel="https">和相对<c:url>

步骤:

  1. 子类SecureChannelProcessorInsecureChannelProcessor覆盖decide()。在decide()中检查负载均衡器发送的标头。

    @Override
    public void decide(FilterInvocation invocation, Collection<ConfigAttribute> config) throws IOException, ServletException {
    
      for (ConfigAttribute attribute : config) {
          if (supports(attribute)) {
              if (invocation.getHttpRequest().
                      getHeader("X-Forwarded-Proto").equals("http")) {
                  entryPoint.commence(invocation.getRequest(),
                      invocation.getResponse());
              }
          }
      }
    }
    
  2. 然后使用BeanPostProcessorChannelDecisionManagerImpl bean上设置这些ChannelProcessors。请参阅此Spring Security FAQ,了解为何/如何使用BeanPostProcessor

答案 1 :(得分:2)

要完成伟大的sourcedelica答案,请输入完整代码:

对于第1步:

@Component
public class SecureChannelProcessorHack extends SecureChannelProcessor {

@Override
public void decide(FilterInvocation invocation, Collection<ConfigAttribute> config) throws IOException, ServletException {
    for (ConfigAttribute attribute : config) {
        if (supports(attribute)) {
            if ("http".equals(invocation.getHttpRequest().getHeader("X-Forwarded-Proto"))) {
                getEntryPoint().commence(invocation.getRequest(),
                        invocation.getResponse());
            }
        }
    }
}
}



@Component
public class InsecureChannelProcessorHack extends InsecureChannelProcessor {

@Override
public void decide(FilterInvocation invocation, Collection<ConfigAttribute> config) throws IOException, ServletException {
    for (ConfigAttribute attribute : config) {
        if (supports(attribute)) {
            if ("https".equals(invocation.getHttpRequest().getHeader("X-Forwarded-Proto"))) {
                getEntryPoint().commence(invocation.getRequest(),
                        invocation.getResponse());
            }
        }
    }
}
}

第2步:

@Configuration
public class LoadBalancerHack implements BeanPostProcessor {

@Inject
SecureChannelProcessorHack secureChannelProcessorHack;

@Inject
InsecureChannelProcessorHack insecureChannelProcessorHack;

@Value("${behind.loadbalancer?false}")
boolean behindLoadBalancer;

@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    return bean;
}

@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    if (behindLoadBalancer && bean instanceof ChannelDecisionManagerImpl) {
        System.out.println("********* Post-processing " + beanName);
        ((ChannelDecisionManagerImpl) bean).setChannelProcessors(newArrayList(
                insecureChannelProcessorHack,
                secureChannelProcessorHack
        ));
    }
    return bean;
}

}

答案 2 :(得分:1)

看起来Grails支持这个作为安全插件的一部分。查看http://grails-plugins.github.com/grails-spring-security-core/docs/manual/guide/17%20Channel%20Security.html的底部,他们谈论检查请求标题,LB将设置。

grails.plugins.springsecurity.secureChannel.useHeaderCheckChannelSecurity = true
grails.plugins.springsecurity.secureChannel.secureHeaderName = '...'
grails.plugins.springsecurity.secureChannel.secureHeaderValue = '...'
grails.plugins.springsecurity.secureChannel.insecureHeaderName = '...'
grails.plugins.springsecurity.secureChannel.insecureHeaderValue = '...'