java 摘要身份验证处理筛选器:doFilter被命中,但'attemptAuthentication'未被命中

2fjabf4q  于 2023-02-07  发布在  Java
关注(0)|答案(3)|浏览(157)

我有下面的filter定义:

@Component
public class JWTAuthenticationFilter extends AbstractAuthenticationProcessingFilter {

    @Autowired
    private UserDetailsService customUserDetailsService;
    @Autowired
    private AuthenticationManager authenticationManager;

    private static Logger logger = LoggerFactory.getLogger(JWTAuthenticationFilter.class);
    private final static UrlPathHelper urlPathHelper = new UrlPathHelper();

    public JWTAuthenticationFilter() {
        super("/**"); // what should I pass here ? 
        setAuthenticationManager(new NoOpAuthenticationManager());
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException {
        Authentication authentication = AuthenticationService.getAuthentication((HttpServletRequest) request, customUserDetailsService);
        return authentication;
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
        filterChain.doFilter(request, response);
    }

    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response,FilterChain chain, Authentication authentication) throws IOException, ServletException {
        super.successfulAuthentication(request, response, chain, authentication);
        logger.debug("successful authentication while attempting to access " + urlPathHelper.getPathWithinApplication((HttpServletRequest) request));
    }

    @Override
    protected void unsuccessfulAuthentication(HttpServletRequest request,
            HttpServletResponse response, AuthenticationException failed)
            throws IOException, ServletException {
        logger.debug("failed authentication while attempting to access " + urlPathHelper.getPathWithinApplication((HttpServletRequest) request));
    }
}

下面是Spring安全的Web配置中的两个configure方法:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
        .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
        .and()
        .csrf().disable()
        .authorizeRequests()
            .anyRequest().authenticated()
        .and()
        .addFilterBefore(jwtAuthenticationFilter,
            UsernamePasswordAuthenticationFilter.class);
}

@Override
public void configure(WebSecurity web) throws Exception {
    web.ignoring()                
            .antMatchers("/login**", "/signup**");
}

这段代码有几个问题:
1.我不希望在调用/login/signup端点时执行过滤器,但即使在调用这两个端点时,doFilter仍然会被命中。

  1. attemptAuthenticationsuccessfulAuthenticationunsuccessfulAuthentication没有被命中,但是doFilter被命中了,为什么,为什么这些方法没有被调用?
    这是怎么回事,为什么?
h6my8fg2

h6my8fg21#

试试这个(但没有测试!):

public class JWTAuthenticationFilter extends AbstractAuthenticationProcessingFilter {

    @Autowired
    private UserDetailsService customUserDetailsService;
    @Autowired
    private AuthenticationManager authenticationManager;

    private static Logger logger = LoggerFactory.getLogger(JWTAuthenticationFilter.class);
    private final static UrlPathHelper urlPathHelper = new UrlPathHelper();

    public JWTAuthenticationFilter() {
        super("/**"); // what should I pass here ? 
        setAuthenticationManager(new NoOpAuthenticationManager());
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException {
        Authentication authentication = AuthenticationService.getAuthentication((HttpServletRequest) request, customUserDetailsService);
        return authentication;
    }

    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response,FilterChain chain, Authentication authentication) throws IOException, ServletException {
        super.successfulAuthentication(request, response, chain, authentication);
        logger.debug("successful authentication while attempting to access " + urlPathHelper.getPathWithinApplication((HttpServletRequest) request));
    }

    @Override
    protected void unsuccessfulAuthentication(HttpServletRequest request,
            HttpServletResponse response, AuthenticationException failed)
            throws IOException, ServletException {
        logger.debug("failed authentication while attempting to access " + urlPathHelper.getPathWithinApplication((HttpServletRequest) request));
    }
}

在配置文件中:

@Bean("jwtAuthenticationFilter")
    public LoginRequestFilter jwtAuthenticationFilter(){
        LoginRequestFilter filter = new LoginRequestFilter();
        filter.setAuthenticationManager(authenticationManager);
        filter.setAuthenticationSuccessHandler(successHandler);
        filter.setAuthenticationFailureHandler(failureHandler);
        //filter.setAuthenticationFailureHandler(failureHandler);
        return filter;
    }

再加上这个

http.authorizeRequests().and()
                .addFilterAt(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
zbdgwd5y

zbdgwd5y2#

1.我不希望在调用/login和/signup端点时执行过滤器,但即使在调用这两个端点时,doFilter仍然会被命中。
虽然我无法解释您编写的两个configure()方法之间的关系,但您可以删除configure(WebSecurity)并在configure(HttpSecurity)中包含所有路径表达式,如下所示:

.authorizeRequests()
        .antMatchers("/login", "/signup")
        .permitAll()
        .and()
    .authorizeRequests()
        .antMatchers("/**")
        .authenticated();
  1. attemptAuthentication,successfulAuthentication和unsuccessfulAuthentication没有被命中,但是doFilter会被命中。为什么?为什么这些方法没有被调用?
    AbstractAuthenticationProcessingFilter.doFilter()通常会调用被覆盖的attemptAuthentication()(以及其他适当的方法)。被覆盖的实现通过将请求无条件地传递给过滤器链的其余部分,有效地将此过滤器转换为“no op”。
rqdpfwrv

rqdpfwrv3#

也许太晚了,但是,我已经给出了一个类似问题的答案,所以它在这里也是有用的:您的自定义实现扩展了UsernamePasswordAuthenticationFilter(它反过来又扩展了AbstractAuthenticationProcessingFilter)。默认情况下,UsernamePasswordAuthenticationFilter用于.formLogin身份验证,处理默认的AntRequestMatcher“/login”。如果使用其他受保护端点,则筛选器的尝试身份验证()方法永远不会得到动作。所以,如果你想使用不同的匹配器(不同的受保护端点),您必须重写默认的AntRequestMatcher。例如,您可以在自定义筛选器构造函数中执行此操作,用这样的方式

super.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher("/auth/signin", "GET"));

相关问题