Forcing Tomcat to use secure JSESSIONID cookie over http

后端 未结 3 1803
礼貌的吻别
礼貌的吻别 2020-12-08 10:29

Is there a way to configure Tomcat 7 to create JSESSIONID cookie with a secure flag in all occasions?

Usual configuration results in Tomcat flagging session cookie

3条回答
  •  伪装坚强ぢ
    2020-12-08 10:53

    Another approach, similar to Mark's, would be to use the SessionCookieConfig, but set it in a context listener from JNDI configuration:

    The code:

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

    Inside web.xml:

    ...
      
        
          org.mitre.caasd.servlet.init.JndiSessionCookieConfigListener
        
      
    ...
    

    In your context.xml:

    ...
    
    ...
    

    This allows you to set all the session cookie configurations at runtime in the deployment environment. Thus, you could use the same webapp (war file) to do development locally (where you would not have https) and in production where you would ALWAYS want https.

    Note, this approach is mentioned in the OWASP documentation

提交回复
热议问题