La documentation indique que org.springframework.web.filter.OncePerRequestFilter
"garantit d'être exécuté uniquement une fois par requête". Dans quelles circonstances un filtre pourrait-il être exécuté plusieurs fois par requête ?
Réponses
Trop de publicités?Dans quelles circonstances un filtre peut-il être exécuté plusieurs fois par requête ?
Vous pourriez avoir le filtre sur la chaîne de filtres plusieurs fois.
La requête pourrait être envoyée à un servlet différent (ou le même) en utilisant le dispatcher de requête.
Un cas d'utilisation courant est dans Spring Security, où la fonctionnalité d'authentification et de contrôle d'accès est généralement implémentée sous forme de filtres placés devant les servlets de l'application principale. Lorsqu'une requête est envoyée en utilisant un dispatcher de requête, elle doit passer à nouveau par la chaîne de filtres (ou éventuellement une différente) avant d'arriver au servlet qui va la traiter. Le problème est que certaines actions de filtre de sécurité ne devraient être effectuées qu'une seule fois pour une requête. D'où le besoin de ce filtre.
Pour comprendre le rôle de OncePerRequestFilter, nous devons d'abord bien comprendre le fonctionnement d'un filtre normal. Lorsque vous voulez exécuter un code spécifique juste avant ou après l'exécution du servlet, vous créez un filtre qui fonctionne comme suit :
code1 ===> exécution du servlet (en utilisant chain.doFilter()) ===> code2
Ainsi, le code1 s'exécute avant le servlet et le code2 après l'exécution du servlet. Cependant, pendant l'exécution du servlet, il peut y avoir une autre requête vers un servlet différent et ce servlet différent a également ce même filtre. Dans ce cas, ce filtre s'exécutera à nouveau.
OncePerRequestFilter prévient ce comportement. Pour notre demande, ce filtre s'exécutera exactement une fois (ni plus ni moins). Ce comportement est très utile lors de la gestion de l'authentification de sécurité.
Sous quelles circonstances un filtre peut-il éventuellement être exécuté plus d'une fois par requête?
Un filtre peut être invoqué dans le cadre de demandes REQUEST ou ASYNC qui se produisent dans des threads séparés. Nous devrions utiliser OncePerRequestFilter car nous effectuons un appel à la base de données pour récupérer le principal ou l'utilisateur authentifié, il n'y a donc aucun intérêt à le faire plus d'une fois. Après cela, nous définissons le principal dans le contexte de sécurité.
Authentication auth = jwtTokenProvider.getAuthentication(token);
SecurityContextHolder.getContext().setAuthentication(auth);
où jwtTokenProvider est votre service pour obtenir une authentification à partir du jeton jwt.
Un type spécial de GenericFilterBean a été introduit pour fonctionner dans l'environnement Servlet 3.0. Cette version a ajouté la possibilité de traiter les requêtes dans des threads séparés. Pour éviter l'exécution de plusieurs filtres dans ce cas, le projet Web Spring définit un type spécial de filtre, OncePerRequestFilter. Il étend directement GenericFilterBean et, comme cette classe, est situé dans le package org.springframework.web.filter. OncePerRequestFilter définit la méthode doFilter. À l'intérieur, il vérifie si le filtre donné a déjà été appliqué en cherchant l'attribut "${nomDuFiltre}.FILTRE" correspondant à true dans les paramètres de la requête. De plus, il définit une méthode abstraite doFilterInternal((HttpServletRequest request, HttpServletResponse response, FilterChain filterChain). Ses implémentations contiendront le code à exécuter par le filtre donné si le filtre n'a pas été appliqué.