90

文档说org.springframework.web.filter.OncePerRequestFilter保证每个请求只执行一次”。在什么情况下,每个请求可能会多次执行过滤器?

4

5 回答 5

77

在什么情况下,每个请求可能会多次执行过滤器?

您可以在过滤器链上多次使用过滤器。

可以使用请求分派器将请求分派到不同(或相同)的 servlet。


一个常见的用例是在 Spring Security 中,其中身份验证和访问控制功能通常作为位于主应用程序 servlet 前面的过滤器来实现。当使用请求分派器分派请求时,它必须再次通过过滤器链(或者可能是另一个过滤器链),然后才能到达将要处理它的 servlet。问题是某些安全过滤器操作应该只对请求执行一次。因此需要这个过滤器。

于 2012-10-31T07:16:36.133 回答
37

要了解OncePerRequestFilter的作用,我们首先需要清楚地了解普通过滤器的行为方式。当您希望在 servlet 执行之前或之后执行某些特定代码时,您可以创建一个过滤器,其工作方式如下:

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

所以code1在servlet之前执行,code2在servlet执行之后执行。但是在这里,当 servlet 执行时,可能会有一些其他请求到不同的 servlet,并且不同的 servlet 也具有相同的过滤器。在这种情况下,此过滤器将再次执行。

OncePerRequestFilter阻止了这种行为。对于我们的一个请求,此过滤器将只执行一次(不多不少)。在使用安全身份验证时,此行为非常有用。

于 2018-08-21T04:19:56.027 回答
6

在 Servlet 3.0 环境中引入了一种特殊的 GenericFilterBean。这个版本增加了在单独的线程中处理请求的可能性。为了避免这种情况下执行多个过滤器,Spring Web 项目定义了一种特殊的过滤器,OncePerRequestFilter。它直接扩展了 GenericFilterBean,并且作为这个类,位于 org.springframework.web.filter 包中。OncePerRequestFilter 定义了 doFilter 方法。在它内部,通过在请求的参数中查找对应于 true 的“${className}.FILTER”属性来检查是否已经应用了给定的过滤器。此外,它定义了一个抽象的 doFilterInternal((HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) 方法。它的实现将包含由给定过滤器执行的代码,如果过滤器没有'

于 2020-01-16T08:36:35.943 回答
5

在什么情况下,每个请求可能会多次执行过滤器?


过滤器可以作为 REQUEST 或 ASYNC 调度的一部分被调用,这些调度发生在单独的线程中。我们应该使用 OncePerRequestFilter,因为我们正在执行数据库调用来检索主体或经过身份验证的用户,多次这样做是没有意义的。之后,我们将主体设置为安全上下文。

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

其中 jwtTokenProvider 是您从 jwt 令牌获取身份验证的服务。

于 2019-10-12T17:14:17.650 回答
0

OncePerRequestFilter 实现逻辑以确保每个请求只执行一次过滤器的 doFilter() 方法。

于 2021-08-26T05:53:19.127 回答