Разгрузка https для балансировки нагрузки с помощью Spring Security - PullRequest
6 голосов
/ 04 ноября 2011

Сейчас балансировщики нагрузки обрабатывают https, а затем передают этот https моим веб-серверам. Так что работа с https удваивается для каждого запроса. То, что я хочу сделать, это полностью разгрузить https, чтобы мои веб-серверы не сталкивались с этим.

Как настроить страницы Spring Security и JSP, если веб-серверы считают все запросы http? Очевидно, мне придется изменить элементы <intercept-url> моей конфигурации, чтобы их атрибут requires-channel всегда был http или any. На моих страницах JSP мне придется добавлять ссылки <c:url value=''/> к ${secureUrl} и ${nonSecureUrl} в зависимости от того, должна ли полученная страница быть https или http. Перенаправления с контроллеров также должны быть изменены следующим образом ... Что-нибудь еще?

Кажется, довольно сложно изменить все ссылки на страницах JSP, чтобы включить схему и хост. Есть ли лучший способ сделать это?

Ответы [ 3 ]

6 голосов
/ 04 ноября 2011

Если вы отключаете SSL на балансировщике нагрузки, то ваш балансировщик нагрузки должен отправить заголовок, указывающий, какой протокол был запрошен изначально. Например, F5 добавляет X-Forwarded-Proto.

Здесь вы можете создавать пользовательские ChannelProcessor, которые смотрят на этот заголовок, а не на request.isSecure(). Затем вы можете продолжить использовать <intercept-url requires-channel="https"> и относительный <c:url>.

шаги:

  1. Подкласс SecureChannelProcessor и InsecureChannelProcessor переопределение 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. Затем установите эти ChannelProcessors для компонента ChannelDecisionManagerImpl , используя BeanPostProcessor. См. FAQ по безопасности Spring о том, почему / как использовать для этого BeanPostProcessor.

2 голосов
/ 18 апреля 2013

Чтобы завершить отличный ответ от 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;
}

}
1 голос
/ 12 октября 2012

Похоже, 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 = '...'
...