什么是OncePerRequestFilter?


75

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

Answers:


62

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

您可以多次将过滤器放在过滤器链上。

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


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


很好的解释。一件事,如果没有请求分发,转发或重定向等,在正常情况下,如果没有在过滤链上多次配置过滤器,过滤器将立即执行一次。–
samshers

32

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

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

因此,code1在servlet之前执行,而code2在servlet执行之后。但是在这里,在执行servlet时,可能会向其他servlet发出其他请求,并且不同的servlet也具有相同的过滤器。在这种情况下,此过滤器将再次执行。

OncePerRequestFilter防止此行为。对于我们的一个请求,此过滤器将恰好执行一次(不多不少)。使用安全认证时,此行为非常有用。


1
您能否详细说明为什么“在使用安全认证时非常有用”
Hilikus

10
是@Hilikus,考虑一下您项目中的常规安全身份验证。我们希望一旦有请求到达您的项目,您就应该对其进行一次授权和认证。然后,如果一切正常,则可以允许该请求访问您的API。OncePerRequestFilter确保此身份验证过程仅发生一次。如果不使用它,则每当我们内部向项目中的其他API发出请求时,由于我们所有的API都具有相同的安全筛选器,因此将再次发生相同的身份验证。
阿曼

@Arman“当我们在内部向项目中的其他API发出请求时”,是指我们将请求分派/转发给具有相同过滤器的另一个URL,而不仅仅是直接调用该类方法。对?
塔伦·库玛

this request can be allowed to hit your APIs.@arman,您能否引用任何示例,为什么我们要从一个api调用中调用其他api-当servlet收到请求时,我们可以调用其他层,例如service / dao等,但这就是java调用。如果您详细说明您的答案或评论,将会更容易理解。
samshers,

3

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


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

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

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


2

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.