Contrôlez la session avec la sécurité de printemps

Contrôler la session avec Spring Security

1. Vue d'ensemble

Dans cet article, nous allons illustrer commentSpring Security allows us to control our HTTP Sessions.

Ce contrôle va du délai d'expiration de session à l'activation de sessions simultanées et à d'autres configurations de sécurité avancées.

Lectures complémentaires:

Récupérer les informations utilisateur dans Spring Security

Comment obtenir l'utilisateur actuellement connecté avec Spring Security.

Read more

Printemps Sécurité Souviens-toi de moi

Cookie Remember Me exemple avec Spring Security.

Read more

Déconnexion de sécurité de printemps

Exemple de déconnexion de printemps: comment configurer l'URL de déconnexion, l'URL de déconnexion et utiliser un bean personnalisé pour gérer des scénarios de déconnexion avancés.

Read more

2. Quand la session est-elle créée?

Nous pouvons contrôler exactement à quel moment notre session est créée et comment Spring Security interagira avec elle:

  • always - une session sera toujours créée si elle n’existe pas déjà

  • ifRequired - une session sera créée uniquement si nécessaire (default)

  • never - le framework ne créera jamais de session lui-même mais il en utilisera une s'il existe déjà

  • stateless - aucune session ne sera créée ou utilisée par Spring Security

...

Configuration Java:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.sessionManagement()
        .sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
}

Il est très important de comprendre quethis configuration only controls what Spring Security does - pas l’application entière. Spring Security peut ne pas créer la session si nous ne l’instruisons pas, mais notre application peut le faire!

Par défaut,Spring Security will create a session when it needs one - c'est «ifRequired».

Poura more stateless application, l'option «never» garantira que Spring Security lui-même ne créera aucune session; cependant, si l'application en crée un, Spring Security l'utilisera.

Enfin, l'option de création de session la plus stricte - «stateless» - est unguarantee that the application will not create any session at all.

C'étaitintroduced au printemps 3.1 et sautera effectivement des parties de la chaîne de filtres Spring Security - principalement les parties liées à la session telles queHttpSessionSecurityContextRepository,SessionManagementFilter,RequestCacheFilter.

Ces mécanismes de contrôle plus stricts impliquent directement quecookies are not used et donceach and every request needs to be re-authenticated. Cette architecture sans état fonctionne bien avec les API REST et leur contrainte d'état sans état. Ils fonctionnent également bien avec des mécanismes d’authentification tels que l’authentification de base et l’authentification Digest.

3. Sous la capuche

Avant d'exécuter le processus d'authentification, Spring Security exécutera un filtre chargé de stocker le contexte de sécurité entre les demandes - lesSecurityContextPersistenceFilter. Le contexte sera stocké selon une stratégie -HttpSessionSecurityContextRepository par défaut - qui utilise la session HTTP comme stockage.

Pour l'attribut strictcreate-session=”stateless”, cette stratégie sera remplacée par un autre -NullSecurityContextRepository - etno session will be created or used pour conserver le contexte.

4. Contrôle de session simultanée

Lorsqu'un utilisateur déjà authentifié tente d'accéder àauthenticate again, l'application peut gérer cet événement de plusieurs manières. Il peut soit invalider la session active de l'utilisateur et authentifier à nouveau l'utilisateur avec une nouvelle session, soit permettre aux deux sessions d'exister simultanément.

La première étape de l'activation de la prise en charge simultanée desession-control consiste à ajouter l'écouteur suivant dans lesweb.xml:


    
      org.springframework.security.web.session.HttpSessionEventPublisher
    

Ou définissez-le comme un haricot - comme suit:

@Bean
public HttpSessionEventPublisher httpSessionEventPublisher() {
    return new HttpSessionEventPublisher();
}

Ceci est essentiel pour vous assurer que le registre de session Spring Security estnotified when the session is destroyed.

Pour activer le scénario qui autorise plusieurs sessions simultanées pour le même utilisateur, l'élément<session-management> doit être utilisé dans la configuration XML:


    
        
    

Ou, via la configuration Java:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.sessionManagement().maximumSessions(2)
}

5. Expiration de la session

5.1. Gestion du délai d'expiration de la session

Une fois la session expirée, si l'utilisateur envoie une requête avec unexpired session id, il sera redirigé vers une URL configurable via l'espace de noms:


    

De même, si l'utilisateur envoie une requête avec un identifiant de session qui n'est pas expiré, mais entièrementinvalid, il sera également redirigé vers une URL configurable:


    ...

La configuration Java correspondante:

http.sessionManagement()
  .expiredUrl("/sessionExpired.html")
  .invalidSessionUrl("/invalidSession.html");

5.2. Configurer le délai de session avec le démarrage du printemps

Nous pouvons facilement configurer la valeur de délai d'expiration de session du serveur intégré à l'aide des propriétés:

server.servlet.session.timeout=15m

Si nous ne spécifions pas l’unité de durée, Spring supposera qu’il s’agit de secondes.

En un mot, avec cette configuration, après 15 minutes d'inactivité, la session expirera. La session qui suit cette période est considérée comme non valide.

Si nous configurons notre projet pour utiliser Tomcat, nous ne devons pas oublier qu'il ne prend en charge que la précision à la minute près, avec une minute au minimum. Cela signifie que si nous spécifions une valeur de délai d'expiration de170s par exemple, cela entraînera un délai d'expiration de 2 minutes.

Enfin, il est important de mentionner que même siSpring Session prend en charge une propriété similaire à cet effet (spring.session.timeout), si cela n’est pas spécifié, la configuration automatique reviendra à la valeur de la propriété que nous avons mentionnée en premier.

6. Empêcher l'utilisation des paramètres d'URL pour le suivi de session

L'exposition des informations de session dans l'URL est unsecurity risk croissant (de la place 7 en 2007 à la place 2 en 2013 sur la liste des 10 meilleurs OWASP).

Starting with Spring 3.0, la logique de réécriture d'URL qui ajouterait lesjsessionid à l'URL peut maintenant être désactivée en définissant lesdisable-url-rewriting=”true” dans l'espace de noms<http>.

Alternativement, à partir de Servlet 3.0, le mécanisme de suivi de session peut également être configuré dans lesweb.xml:


     COOKIE

Et par programme:

servletContext.setSessionTrackingModes(EnumSet.of(SessionTrackingMode.COOKIE));

Ceci choisit où stocker lesJSESSIONID - dans le cookie ou dans un paramètre d'URL.

7. Protection contre la fixation de session avec Spring Security

L'infrastructure offre une protection contre les attaques typiques de Session Fixation en configurant le sort d'une session existante lorsque l'utilisateur tente de s'authentifier à nouveau:

 ...

La configuration Java correspondante:

http.sessionManagement()
  .sessionFixation().migrateSession()

Par défaut, Spring Security a cette protection activée («migrateSession») - lors de l'authentification, une nouvelle session HTTP est créée, l'ancienne est invalidée et les attributs de l'ancienne session sont copiés.

Si ce n'est pas le comportement souhaité, deux autres options sont disponibles:

  • lorsque «none» est défini, la session d'origine ne sera pas invalidée

  • lorsque «newSession» est défini, une session propre sera créée sans qu'aucun des attributs de l'ancienne session ne soit copié

Ensuite, nous verrons comment sécuriser notre cookie de session.

We can use the httpOnly and secure flags to secure our session cookie:

  • httpOnly: si true, le script du navigateur ne pourra pas accéder au cookie

  • secure: si vrai, le cookie sera envoyé uniquement via une connexion HTTPS

Nous pouvons définir ces indicateurs pour notre cookie de session dans lesweb.xml:


    1
    
        true
        true
    

Cette option de configuration est disponible depuis le servlet Java 3. Par défaut,http-only est vrai etsecure est faux.

Jetons également un œil à la configuration Java correspondante:

public class MainWebAppInitializer implements WebApplicationInitializer {
    @Override
    public void onStartup(ServletContext sc) throws ServletException {
        // ...
        sc.getSessionCookieConfig().setHttpOnly(true);
        sc.getSessionCookieConfig().setSecure(true);
    }
}

If we’re using Spring Boot, we can set these flags in our application.properties:

server.servlet.session.cookie.http-only=true
server.servlet.session.cookie.secure=true

Enfin, nous pouvons également y parvenir manuellement en utilisant unFilter:

public class SessionFilter implements Filter {
    @Override
    public void doFilter(
      ServletRequest request, ServletResponse response, FilterChain chain)
      throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse res = (HttpServletResponse) response;
        Cookie[] allCookies = req.getCookies();
        if (allCookies != null) {
            Cookie session =
              Arrays.stream(allCookies).filter(x -> x.getName().equals("JSESSIONID"))
                    .findFirst().orElse(null);

            if (session != null) {
                session.setHttpOnly(true);
                session.setSecure(true);
                res.addCookie(session);
            }
        }
        chain.doFilter(req, res);
    }
}

9. Travailler avec la session

9.1. Beans à portée de session

Un bean peut être défini avec la portéesession simplement en utilisant l'annotation @Scope sur les beans déclarés dans le contexte web:

@Component
@Scope("session")
public class Foo { .. }

Ou avec XML:

Ensuite, le haricot peut simplement être injecté dans un autre haricot:

@Autowired
private Foo theFoo;

Et Spring liera le nouveau bean au cycle de vie de la session HTTP.

9.2. Injection de la session brute dans un contrôleur

La session HTTP brute peut également être injectée directement dans une méthodeController:

@RequestMapping(..)
public void fooMethod(HttpSession session) {
    session.setAttribute(Constants.FOO, new Foo());
    //...
    Foo foo = (Foo) session.getAttribute(Constants.FOO);
}

9.3. Obtention de la session brute

La session HTTP actuelle peut également être obtenue par programme via lesraw Servlet API:

ServletRequestAttributes attr = (ServletRequestAttributes)
    RequestContextHolder.currentRequestAttributes();
HttpSession session= attr.getRequest().getSession(true); // true == allow create

10. Conclusion

Dans cet article, nous avons abordé la gestion des sessions avec Spring Security. De plus, le Spring Reference contient un très bonFAQ on Session Management.

Comme toujours, le code présenté dans cet article est disponibleover on Github. Ceci est un projet basé sur Maven, il devrait donc être facile à importer et à exécuter tel quel.