web-dev-qa-db-fra.com

Forcer Tomcat à utiliser un cookie JSESSIONID sécurisé sur http

Existe-t-il un moyen de configurer Tomcat 7 pour créer un cookie JSESSIONID avec un indicateur sécurisé en toutes occasions?

La configuration habituelle entraîne un cookie de session de signalisation Tomcat avec indicateur sécurisé uniquement si la connexion est établie via https. Cependant, dans mon scénario de production, Tomcat est derrière un proxy inverse/équilibreur de charge qui gère (et met fin) à la connexion https et contacte Tomcat via http.

Puis-je en quelque sorte forcer un indicateur sécurisé sur le cookie de session avec Tomcat, même si la connexion est établie via http simple?

25
Kresimir Nesek

Au final, contrairement à mes premiers tests, la solution web.xml a fonctionné pour moi sur Tomcat 7.

Par exemple. J'ai ajouté cet extrait à web.xml et il marque le cookie de session comme sécurisé même lorsque le proxy inverse contacte Tomcat via HTTP simple.

<session-config>
    <cookie-config>
        <http-only>true</http-only>
        <secure>true</secure>
    </cookie-config>
</session-config>
35
Kresimir Nesek

ServletContext.getSessionCookieConfig (). SetSecure (true)

8
Mark Thomas

Une autre approche, similaire à celle de Mark, serait d'utiliser le SessionCookieConfig, mais le placer dans un écouteur de contexte à partir de la configuration JNDI:

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

À l'intérieur de web.xml:

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

Dans votre context.xml:

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

Cela vous permet de définir toutes les configurations de cookies de session lors de l'exécution dans l'environnement de déploiement . Ainsi, vous pourriez utiliser la même webapp (fichier war) pour faire du développement localement (où vous n'auriez pas https) et en production où vous le feriez [~ # ~] toujours [~ # ~] veulent https.

Remarque, cette approche est mentionnée dans la documentation OWASP

1
Lucas