Prise en charge asynchrone du servlet 3 avec Spring MVC et Spring Security

Prise en charge asynchrone de Servlet 3 avec Spring MVC et Spring Security

1. introduction

Dans ce rapide tutoriel, nous allons nous concentrer surthe Servlet 3 support for async requests, and how Spring MVC and Spring Security handle these.

La motivation la plus élémentaire en matière d’asynchronisme dans les applications Web consiste à traiter les demandes de longue durée. Dans la plupart des cas d'utilisation, nous devons nous assurer que le principal Spring Security est propagé à ces threads.

Et, bien sûr, Spring Securityintegrates with @Asyncort du cadre de MVC et traite également les requêtes HTTP.

2. Dépendances Maven

Afin d'utiliser l'intégration asynchrone dans Spring MVC, nous devons inclure les dépendances suivantes dans nospom.xml:


    org.springframework.security
    spring-security-web
    4.2.1.RELEASE


    org.springframework.security
    spring-security-config
    4.2.1.RELEASE

La dernière version des dépendances de Spring Security peut être trouvéehere.

3. Spring MVC et@Async

Selon lesdocs officiels, Spring Security s'intègre àWebAsyncManager.

La première étape consiste à s'assurer que notrespringSecurityFilterChain est configuré pour traiter les requêtes asynchrones. Nous pouvons le faire soit dans la configuration Java, en ajoutant la ligne suivante à notre classe de configurationServlet:

dispatcher.setAsyncSupported(true);

ou en configuration XML:


    springSecurityFilterChain
    org.springframework.web.filter.DelegatingFilterProxy
    true


    springSecurityFilterChain
    /*
    REQUEST
    ASYNC

Nous devons également activer le paramètreasync-supported dans notre configuration de servlet:


    ...
    true
    ...

Nous sommes maintenant prêts à envoyer des requêtes asynchrones avecSecurityContext propagées avec elles.

Les mécanismes internes de Spring Security garantiront que nosSecurityContext ne sont plus effacés lorsqu'une réponse est validée dans un autreThread, ce qui entraîne une déconnexion de l'utilisateur.

4. Cas d'utilisation

Voyons cela en action avec un exemple simple:

@Override
public Callable checkIfPrincipalPropagated() {
    Object before
      = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
    log.info("Before new thread: " + before);

    return new Callable() {
        public Boolean call() throws Exception {
            Object after
              = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
            log.info("New thread: " + after);
            return before == after;
        }
    };
}

Nous voulons vérifier si le SpringSecurityContext est propagé vers le nouveau thread.

La méthode présentée ci-dessus verra automatiquement sesCallable exécutés avec lesSecurityContext inclus, comme on le voit dans les logs:

web - 2017-01-02 10:42:19,011 [http-nio-8081-exec-3] INFO
  o.example.web.service.AsyncService - Before new thread:
  [email protected]:
  Username: temporary; Password: [PROTECTED]; Enabled: true;
  AccountNonExpired: true; credentialsNonExpired: true;
  AccountNonLocked: true; Granted Authorities: ROLE_ADMIN

web - 2017-01-02 10:42:19,020 [MvcAsync1] INFO
  o.example.web.service.AsyncService - New thread:
  [email protected]:
  Username: temporary; Password: [PROTECTED]; Enabled: true;
  AccountNonExpired: true; credentialsNonExpired: true;
  AccountNonLocked: true; Granted Authorities: ROLE_ADMIN

Sans paramétrer lesSecurityContext à propager, la deuxième requête se terminera avec la valeurnull.

Il existe également d'autres cas d'utilisation importants pour utiliser des requêtes asynchrones avec desSecurityContext propagés:

  • nous voulons faire plusieurs requêtes externes pouvant s'exécuter en parallèle et dont l'exécution peut prendre beaucoup de temps

  • nous avons un traitement important à faire localement et notre requête externe peut être exécutée parallèlement à celle

  • d'autres représentent des scénarios incendiaires, comme par exemple l'envoi d'un courrier électronique

Notez que, si nos appels à plusieurs méthodes étaient auparavant chaînés de manière synchrone, leur conversion en une approche asynchrone peut nécessiter une synchronisation des résultats.

5. Conclusion

Dans ce court didacticiel, nous avons illustré le support Spring pour le traitement des requêtes asynchrones dans un contexte authentifié.

Du point de vue des modèles de programmation, les nouvelles fonctionnalités semblent d'une simplicité trompeuse. Mais il y a certainement certains aspects qui nécessitent une compréhension plus approfondie.

Cet exemple est également disponible en tant que projet Mavenover on Github.