2011-11-03 18 views
6

En este momento, los equilibradores de carga manejan https y luego transfieren ese https a mis servidores web. Así que lidiar con https doble para cada solicitud. Lo que quiero hacer es descargar por completo https para que mis servidores web no tengan que lidiar con eso.Descarga de https para equilibradores de carga con Spring Security

¿Cómo configuro Spring Security y las páginas JSP dado que los servidores web piensan que todas las solicitudes son http? Obviamente tendré que modificar los elementos <intercept-url> de mi configuración para que su atributo requires-channel siempre sea http o any. En mis páginas JSP tendré que anteponer los enlaces <c:url value=''/> con ${secureUrl} y ${nonSecureUrl} dependiendo de si la página resultante debe ser https o http. Los redireccionamientos de los controladores deben modificarse así también ... ¿Algo más?

Parece bastante molesto modificar todos los enlaces en las páginas JSP para incluir también el esquema y el host. ¿Hay una mejor manera de hacer eso?

Respuesta

6

Si finaliza SSL en el equilibrador de carga, su equilibrador de carga debe enviar un encabezado que indique qué protocolo se solicitó originalmente. Por ejemplo, el F5 agrega X-Forwarded-Proto.

Desde aquí puede crear ChannelProcessor personalizados que miren este encabezado en lugar de mirar request.isSecure(). Luego puede continuar usando <intercept-url requires-channel="https"> y relativa <c:url>.

Los pasos:

  1. Subclase SecureChannelProcessor y InsecureChannelProcessor anulando decide(). En decide(), compruebe el encabezado enviado por su equilibrador de carga.

    @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. asentando después estos ChannelProcessors en el frijol ChannelDecisionManagerImpl utilizando un BeanPostProcessor. Consulte esto Spring Security FAQ sobre por qué/cómo usar un BeanPostProcessor para esto.

+0

probado los pasos anteriores, Decidir que el método no se llama, ¿hay algo más que necesitemos configurar? –

1

Parece que Grails admite esto como parte del complemento de seguridad. Consulte la sección inferior de http://grails-plugins.github.com/grails-spring-security-core/docs/manual/guide/17%20Channel%20Security.html donde hablan sobre la comprobación de los encabezados de solicitud, que el LB establecerá.

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 = '...' 
2

Para completar el gran respuesta sourcedelica, aquí está el código completo:

Para el Paso 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()); 
      } 
     } 
    } 
} 
} 

y el Paso 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; 
} 

} 
Cuestiones relacionadas