2011-11-03 7 views
6

Al momento, i bilanciatori del carico gestiscono https e quindi passano lungo questi https ai miei server web. Quindi si tratta di https double per ogni richiesta. Quello che voglio fare è scaricare completamente https in modo che i miei server web non debbano occuparsene.Offloading https per caricare i bilanciatori con Spring Security

Come configurare le pagine Spring Security e JSP dato che i server Web pensano che tutte le richieste siano http? Ovviamente dovrò modificare gli elementi <intercept-url> della mia configurazione affinché l'attributo requires-channel sia sempre http o any. Nelle mie pagine JSP dovrò anteporre i collegamenti <c:url value=''/> a ${secureUrl} e ${nonSecureUrl} a seconda che la pagina risultante debba essere https o http. Anche i reindirizzamenti dai controller devono essere modificati in questo modo ... Qualcos'altro?

Sembra quasi un problema modificare tutti i collegamenti nelle pagine JSP per includere lo schema e l'host. C'è un modo migliore per farlo?

risposta

6

Se si termina SSL con il servizio di bilanciamento del carico, il bilanciamento del carico dovrebbe inviare un'intestazione che indica quale protocollo è stato originariamente richiesto. Ad esempio, F5 aggiunge X-Forwarded-Proto.

Da qui è possibile creare ChannelProcessor s personalizzati che guardano questa intestazione invece di guardare request.isSecure(). Quindi è possibile continuare a utilizzare <intercept-url requires-channel="https"> e relativo <c:url>.

I passi:

  1. sottoclasse SecureChannelProcessor e InsecureChannelProcessor sovrascrivendo decide(). In decide() controllare l'intestazione inviata dal servizio di bilanciamento del carico.

    @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. Poi impostare questi ChannelProcessors sul fagiolo ChannelDecisionManagerImpl utilizzando un BeanPostProcessor. Vedere questo Spring Security FAQ su perché/come utilizzare uno BeanPostProcessor per questo.

+0

provato i passaggi precedenti, Decidi che il metodo non viene chiamato, c'è qualcos'altro che dobbiamo configurare? –

1

Sembra che Grails supporti questo come parte del plugin di sicurezza. Controlla la sezione inferiore di http://grails-plugins.github.com/grails-spring-security-core/docs/manual/guide/17%20Channel%20Security.html dove si parla di controllare le intestazioni delle richieste, che verranno impostate dal 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 = '...' 
2

Per completare la grande risposta sourcedelica, ecco il codice completo:

Per Passaggio 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()); 
      } 
     } 
    } 
} 
} 

e Step 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; 
} 

}