Was ist OncePerRequestFilter?

74

In der Dokumentation heißt es org.springframework.web.filter.OncePerRequestFilter" Garantien müssen nur einmal pro Anfrage ausgeführt werden ". Unter welchen Umständen kann ein Filter möglicherweise mehr als einmal pro Anforderung ausgeführt werden?

Somu
quelle

Antworten:

60

Unter welchen Umständen kann ein Filter möglicherweise mehr als einmal pro Anforderung ausgeführt werden?

Sie können den Filter mehrmals in der Filterkette haben.

Die Anforderung kann mithilfe des Anforderungsverteilers an ein anderes (oder dasselbe) Servlet gesendet werden.


Ein häufiger Anwendungsfall ist Spring Security, wo Authentifizierungs- und Zugriffssteuerungsfunktionen normalerweise als Filter implementiert werden, die sich vor den Hauptanwendungsservlets befinden. Wenn eine Anforderung mit einem Anforderungs-Dispatcher versendet wird, muss sie die Filterkette erneut durchlaufen (oder möglicherweise eine andere), bevor sie zu dem Servlet gelangt, das sie bearbeiten wird. Das Problem ist, dass einige der Sicherheitsfilteraktionen für eine Anforderung nur einmal ausgeführt werden sollten. Daher die Notwendigkeit für diesen Filter.

Stephen C.
quelle
30

Um die Rolle von OncePerRequestFilter zu verstehen , müssen wir zunächst klar verstehen, wie sich ein normaler Filter verhält. Wenn Sie möchten, dass ein bestimmter Code unmittelbar vor oder nach der Servlet-Ausführung ausgeführt wird, erstellen Sie einen Filter, der wie folgt funktioniert:

code1   ===>   servlet execution (using chain.doFilter())   ===>    code2

Code1 wird also vor dem Servlet und Code2 nach der Servlet-Ausführung ausgeführt. Während der Servlet-Ausführung kann es jedoch zu einer anderen Anforderung an ein anderes Servlet kommen, und dieses andere Servlet hat auch denselben Filter. In diesem Fall wird dieser Filter erneut ausgeführt.

OncePerRequestFilter verhindert dieses Verhalten. Für unsere eine Anfrage wird dieser Filter genau einmal ausgeführt (nicht mehr und nicht weniger). Dieses Verhalten ist sehr nützlich, wenn Sie mit der Sicherheitsauthentifizierung arbeiten.

Arman
quelle
1
Können Sie bitte erläutern, warum dies "sehr nützlich bei der Arbeit mit Sicherheitsauthentifizierung" ist
Hilikus
10
Ja @Hilikus, Denken Sie an eine allgemeine Sicherheitsauthentifizierung in Ihrem Projekt. Wir gehen davon aus, dass Sie eine Anfrage, sobald sie bei Ihrem Projekt eingeht, einmal autorisieren und authentifizieren sollten. Wenn dann alles in Ordnung zu sein scheint, kann diese Anfrage Ihre APIs treffen. OncePerRequestFilter stellt sicher, dass dieser Authentifizierungsprozess nur einmal stattfindet. Wenn wir dies nicht verwenden, wird bei jeder internen Anforderung an eine andere API in unserem Projekt dieselbe Authentifizierung erneut durchgeführt, da alle unsere APIs denselben Sicherheitsfilter haben.
Arman
@Arman Mit "wann immer wir intern eine Anfrage an eine andere API in unserem Projekt stellen" meinen Sie, wann immer wir die Anfrage an eine andere URL mit demselben Filter senden / weiterleiten und nicht nur diese Klassenmethode direkt aufrufen. Richtig?
Tarun Kumar
3

Unter welchen Umständen kann ein Filter möglicherweise mehr als einmal pro Anforderung ausgeführt werden?


Ein Filter kann als Teil eines REQUEST- oder ASYNC-Versands aufgerufen werden, der in separaten Threads erfolgt. Wir sollten OncePerRequestFilter verwenden, da wir einen Datenbankaufruf ausführen, um den Principal oder den authentifizierten Benutzer abzurufen. Es macht keinen Sinn, dies mehr als einmal zu tun. Danach setzen wir den Principal auf den Sicherheitskontext.

Authentication auth = jwtTokenProvider.getAuthentication(token);
SecurityContextHolder.getContext().setAuthentication(auth);

Dabei ist jwtTokenProvider Ihr Dienst zum Abrufen der Authentifizierung vom jwt-Token.

Prashant Chamoli
quelle
2

Eine spezielle Art von GenericFilterBean wurde eingeführt, um in der Servlet 3.0-Umgebung zu leben. Diese Version hat die Möglichkeit hinzugefügt, die Anforderungen in separaten Threads zu behandeln. Um die Ausführung mehrerer Filter in diesem Fall zu vermeiden, definiert das Spring Web-Projekt eine spezielle Art von Filter, OncePerRequestFilter. Es erweitert direkt GenericFilterBean und befindet sich als diese Klasse im Paket org.springframework.web.filter. OncePerRequestFilter definiert die doFilter-Methode. Darin wird überprüft, ob der angegebene Filter bereits angewendet wurde, indem nach dem Attribut "$ {className} .FILTER" gesucht wird, das in den Parametern der Anforderung true entspricht. Darüber hinaus wird eine abstrakte Methode doFilterInternal ((HttpServletRequest-Anforderung, HttpServletResponse-Antwort, FilterChain filterChain) definiert. Ihre Implementierungen enthalten den Code, der von einem bestimmten Filter ausgeführt werden soll, wenn der Filter nicht '

Nilesh
quelle