2013-02-20 21 views
21

Czy istnieje sposób, aby skonfigurować Tomcat 7, aby utworzyć plik cookie JSESSIONID z bezpieczną flagą przy każdej okazji?Zmuszając Tomcat do używania bezpiecznego pliku cookie JSESSIONID przez http

Zwykła konfiguracja powoduje, że plik cookie oznaczający flagę Tomcat jest chroniony flagą tylko wtedy, gdy połączenie jest nawiązywane przez https. Jednak w moim scenariuszu produkcji Tomcat znajduje się za odwrotnym proxy/load balancer, który obsługuje (i kończy) połączenie https i tomcat kontaktów przez http.

Czy mogę w jakiś sposób wymusić oznaczenie bezpiecznej flagi na pliku cookie sesji z Tomcat, mimo że połączenie odbywa się za pomocą zwykłego http?

Odpowiedz

29

W końcu, w przeciwieństwie do moich początkowych testach rozwiązanie web.xml pracował dla mnie na Tomcat 7.

Np Dodałem ten fragment do pliku web.xml i oznacza to, że sesyjny plik cookie jest bezpieczny nawet wtedy, gdy serwer proxy odwrotnego proxy działa na zwykłym HTTP.

<session-config> 
    <cookie-config> 
     <http-only>true</http-only> 
     <secure>true</secure> 
    </cookie-config> 
</session-config> 
7

ServletContext.getSessionCookieConfig(). SetSecure (true)

+1

Ponieważ aplet 3 http://docs.oracle.com/javaee/6/api/javax/servlet/SessionCookieConfig.html –

1

Innym podejściem, podobnie jak Mark, byłoby użyć SessionCookieConfig, ale ustawić go w słuchacza od kontekstu JNDI konfiguracji:

Kod:

import javax.naming.Context; 
import javax.naming.InitialContext; 
import javax.naming.NamingException; 
import javax.servlet.ServletContextEvent; 
import javax.servlet.ServletContextListener; 
import javax.servlet.SessionCookieConfig; 


import org.slf4j.Logger; 
import org.slf4j.LoggerFactory; 


public class JndiSessionCookieConfigListener implements ServletContextListener { 
    private static final Logger logger = LoggerFactory.getLogger(JndiSessionCookieConfigListener.class); 

    private volatile Context jndiSessionCookieConfig; 
    private volatile SessionCookieConfig sessionCookieConfig; 

    @Override 
    public void contextInitialized(ServletContextEvent sce) { 
     String listenerName = getClass().getSimpleName(); 
     try { 
      logger.info("JNDI override session cookie config found for {}", listenerName); 
      jndiSessionCookieConfig = (Context) new InitialContext().lookup(
        "java:comp/env/" + listenerName); 
     } 
     catch (NamingException e) { 
      logger.info("No JNDI override session cookie config found for {}", listenerName); 
     } 

     sessionCookieConfig = sce.getServletContext().getSessionCookieConfig(); 

     String comment = getString("comment"); 
     if (comment != null) { 
      logger.debug("\t[comment]: [{}]", comment); 
      sessionCookieConfig.setComment(comment); 
     } 

     String domain = getString("domain"); 
     if (domain != null) { 
      logger.debug("\t[domain]: [{}]", domain); 
      sessionCookieConfig.setDomain(domain); 
     } 

     Boolean httpOnly = getBoolean("http-only"); 
     if (httpOnly == null) { 
      sessionCookieConfig.setHttpOnly(true); 
     } 
     else { 
      logger.debug("\t[http-only]: [{}]", httpOnly); 
      sessionCookieConfig.setHttpOnly(httpOnly); 
     } 

     Integer maxAge = getInteger("max-age"); 
     if (maxAge != null) { 
      sessionCookieConfig.setMaxAge(maxAge); 
     } 

     String name = getString("name"); 
     if (name != null) { 
      logger.debug("\t[name]: [{}]", name); 
      sessionCookieConfig.setName(name); 
     } 

     String path = getString("path"); 
     if (path != null) { 
      logger.debug("\t[path]: [{}]", path); 
      sessionCookieConfig.setPath(path); 
     } 

     Boolean secure = getBoolean("secure"); 
     if (secure == null) { 
      sessionCookieConfig.setSecure(true); 
     } 
     else { 
      logger.debug("\t[secure]: [{}]", secure); 
      sessionCookieConfig.setSecure(secure); 
     } 
    } 

    @Override 
    public void contextDestroyed(ServletContextEvent sce) { 
    } 

    private Boolean getBoolean(String name) { 
     Object value; 
     try { 
      value = jndiSessionCookieConfig.lookup(name); 
      if (value instanceof Boolean) { 
       return (Boolean)value; 
      } 
      else { 
       return Boolean.valueOf(value.toString()); 
      } 
     } 
     catch (NamingException e) { 
      return null; 
     } 
    } 

    private Integer getInteger(String name) { 
     Object value; 
     try { 
      value = jndiSessionCookieConfig.lookup(name); 
      if (value instanceof Integer) { 
       return (Integer)value; 
      } 
      else { 
       return Integer.valueOf(value.toString()); 
      } 
     } 
     catch (NamingException e) { 
      return null; 
     } 
    } 

    private String getString(String name) { 
     Object value; 
     try { 
      value = jndiSessionCookieConfig.lookup(name); 
      return value.toString(); 
     } 
     catch (NamingException e) { 
      return null; 
     } 
    } 
} 

Wewnątrz web.xml :

... 
    <listener> 
    <listener-class> 
     org.mitre.caasd.servlet.init.JndiSessionCookieConfigListener 
    </listener-class> 
    </listener> 
... 

W swojej context.xml:

... 
<Environment name="JndiSessionCookieConfigListener/secure" 
    type="java.lang.String" 
    override="false" 
    value="true" /> 
... 

To pozwala ustawić wszystkie konfiguracje ciasteczka sesyjnego w czasie wykonywania w środowisku wdrażania. W ten sposób można użyć tej samej aplikacji webowej (pliku wojennego) do lokalnego programowania (gdzie nie miałbyś https) i do produkcji, w której chcesz ZAWSZE chcieć https.

Uwaga, takie podejście jest wymienione w OWASP documentation

Powiązane problemy