首页 > 解决方案 > 什么时候使用 UsernamePasswordAuthenticationFilter?

问题描述

这是我正在合作的一些代码的简化示例。过滤器已设置MyCustomFilter为在 之后运行UsernamePasswordAuthenticationFilter.class

如果我运行服务器并发出请求,只需对任何端点(即使是不存在的端点)发出一个普通的 GET 请求,"this filter is being hit"内部MyCustomFilter打印(两次)。

我在每个方法上都设置了断点UsernamePasswordAuthenticationFilter.java,包括构造函数,它永远不会被命中。

那么我的after过滤器是如何被调用的呢?

DemoApplication.java

@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

}

AuthConfig.java

@Configuration
@EnableWebSecurity
public class AuthConfig extends WebSecurityConfigurerAdapter {

  protected void configure(HttpSecurity http) throws Exception {
    http.csrf().disable()
        .addFilterAfter(new MyCustomFilter(), UsernamePasswordAuthenticationFilter.class);
  }

}

MyCustomFilter.java

public class MyCustomFilter implements Filter {
    
  @Override
  public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain)
      throws IOException, ServletException {
    System.out.println("this filter is being hit");
    chain.doFilter(request, response);
  }
     // other overrides...
}

标签: javaspring-security

解决方案


根据文档,过滤器将在您的请求被路由到控制器之前被调用。这就是为什么即使您没有方法端点也能看到它的原因。

public interface Filter

A filter is an object that performs filtering tasks on either the request to a resource (a servlet or static content), or on the response from a resource, or both.

Filters perform filtering in the doFilter method. Every Filter has access to a FilterConfig object from which it can obtain its initialization parameters, a reference to the ServletContext which it can use, for example, to load resources needed for filtering tasks.


  void  doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
  

每次由于客户端对链末端资源的请求,请求/响应对通过链时,容器都会调用 Filter 的 doFilter 方法。

您还有 2 个其他方法(init() 和 destroy() 可用于查看过滤器的生命周期。

https://tomcat.apache.org/tomcat-5.5-doc/servletapi/javax/servlet/Filter.html

-- 已编辑 ---

我相信您缺少 authorizeRequests() ,这就是未触发 UsernameAndPasswordAuthenticationFilter 的原因。

        http.csrf()
        .disable()
        .authorizeRequests()
        .anyRequest().authenticated()
        .and()
        .addFilterAfter(new CustomFilter()), UsernamePasswordAuthenticationFilter.class)

-- 已编辑 --

看来您可能没有用户名/密码表格?因此,没有根据需要调用 UsernamePasswordAuthenticationFilter 。

过滤器具有特定的顺序,并且是链式的:如果给定的过滤器不适用,则链将跳过它并继续按顺序执行下一个过滤器。

默认顺序为:

ChannelProcessingFilter
ConcurrentSessionFilter
SecurityContextPersistenceFilter
LogoutFilter
X509AuthenticationFilter
AbstractPreAuthenticatedProcessingFilter
CasAuthenticationFilter
UsernamePasswordAuthenticationFilter
<---- Your CustomFilter Here --->
ConcurrentSessionFilter
OpenIDAuthenticationFilter
DefaultLoginPageGeneratingFilter
ConcurrentSessionFilter
DigestAuthenticationFilter
BasicAuthenticationFilter
RequestCacheAwareFilter
SecurityContextHolderAwareRequestFilter
JaasApiIntegrationFilter
RememberMeAuthenticationFilter
AnonymousAuthenticationFilter
SessionManagementFilter
ExceptionTranslationFilter
FilterSecurityInterceptor
SwitchUserFilter

public class UsernamePasswordAuthenticationFilter
extends AbstractAuthenticationProcessingFilter

Processes an authentication form submission. Called AuthenticationProcessingFilter prior to Spring Security 3.0.

Login forms must present two parameters to this filter: a username and password. The default parameter names to use are contained in the

静态字段 SPRING_SECURITY_FORM_USERNAME_KEY 和 SPRING_SECURITY_FORM_PASSWORD_KEY。参数名称也可以通过设置 usernameParameter 和 passwordParameter 属性来更改。

This filter by default responds to the URL /login.

默认情况下,UsernamePasswordAuthenticationFilter 仅通过访问 /login 触发。


推荐阅读