2013-02-20 54 views
21

有没有办法配置Tomcat 7在所有场合使用安全标志创建JSESSIONID cookie?强制Tomcat使用安全的JSESSIONID Cookie通过http

只有在通过https进行连接时,通常的配置才会导致Tomcat将会话cookie标记为带有安全标志的会话cookie。但是在我的生产场景中,Tomcat位于反向代理/负载平衡器的后面,该平衡器负责处理(并终止)https连接,并通过http联系tomcat。

我可以以某种方式强制会话cookie上的安全标志与Tomcat,即使通过纯http进行连接?

回答

29

最终,出乎我的初步测试,web.xml文件解决方案为我在Tomcat 7

例如我将这段代码添加到web.xml中,即使反向代理通过普通HTTP联系tomcat,它也会将会话cookie标记为安全。

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

ServletContext.getSessionCookieConfig()。setSecure(真)

+1

提到由于servlet的3 http://docs.oracle.com/javaee/6/api/javax/servlet/SessionCookieConfig.html – 2014-02-07 21:45:37

1

另一种方法,类似于Mark的,是使用了SessionCookieConfig,但是从JNDI配置设置它在上下文监听器:

代码:

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

web.xml中:

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

在你的context.xml中:

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

这使您可以在部署环境的运行时中设置所有会话Cookie配置。因此,您可以使用相同的webapp(war文件)在本地进行开发(您不会使用https),并且在生产中您会希望使用https。

注意,这种方法在OWASP documentation