security未设权限的路径不能通过AuthorizationFilter

security版本:3.0.1

Security配置:

    SecurityFilterChain filterChain(HttpSecurity http) throws Exception {

        // 禁用默认的JSP表单登录
//        http.formLogin(form -> form.loginPage("/login"));
//        http.logout(logout -> logout.logoutSuccessUrl("/success"));

        // 插入自定义登录过滤器
        http.addFilter(wxAuthenticationFilter());

        // 插入JWT认证过滤器,在登录认证过滤器之前
        http.addFilterBefore(wxJwtAuthenticationFilter(), WxAuthenticationFilter.class);

        http.anonymous();

        http.httpBasic().disable();

        // 验证路径
        http.authorizeHttpRequests().requestMatchers("/").permitAll().and()
            .authorizeHttpRequests().anyRequest().authenticated();

        // 设置session无状态
        http.sessionManagement(s -> s.sessionCreationPolicy(SessionCreationPolicy.STATELESS));

        // 设置未授权请求异常处理
        http.exceptionHandling(
                e -> e.accessDeniedHandler(accessDeniedHandler()).authenticationEntryPoint(authenticationEntryPoint()));

        http.csrf().disable();

        return http.build();
    }

@Bean
public WebSecurityCustomizer webSecurityCustomizer() {
        return web -> web.ignoring().requestMatchers("/ignore1", "/ignore2");
}
  1. 重写了认证相关的过滤器,WxAuthenticationFilter替换了UsernamePasswordAuthenticationFilter。
    而JWT认证是在WxAuthenticationFilter之前。

  2. 配置了两个ignore1ignore2,不通过security过滤器。

在实际访问/ignore1路径时,还是走了security过滤器,并且在AnonymousAuthenticationFilter中给了anonymousUser角色,在通过AuthorizationFilter时拒绝了请求并抛出了Access Denice。

-具体debug是AuthenticatedAuthorizationManager的135行返回false:

而AuthorizationFilter根据这个条件在97行拒绝了访问

1.security中管理认证的核心是 AuthenticationManagerAuthenticationProvider,也就说说 AuthenticationManager中有个list的provider,里面的任何一个都可以证明校验是否通过,而你仅仅是写了个filter,然后把filter置换了下顺序;所以具体执行要看下 ProviderManager有没有管理你的AuthenticationProvider,其次才能决定你的执行filter绑定的provider里面是否认证成功,如果成功了,那么providermanager整体放行,再次进行自定义的service(这个service也是可以通过自定义AuthenticationProvider绑定的)
2.官方推荐的路径放行URL配置实际上在 HttpSecurity,你配置的那里也行,也没问题。

1 个赞

具体可以看下文档 官方的架构说明:Servlet 认证架构 :: Spring Security Reference

1 个赞

还有个主要配置我忘了放了:

    @Bean
    public WxAuthenticationFilter wxAuthenticationFilter() throws Exception {
        WxAuthenticationFilter wxAuthenticationFilter = new WxAuthenticationFilter(
                authenticationManager(), "/user/login");
        wxAuthenticationFilter.setAuthenticationManager(wxAuthenticationManager);
        return wxAuthenticationFilter;
    }

这里我直接覆盖了官方的AuthenticationManager配置,WxAuthenticationFilter在authenticate时候直接调用WxAuthenticationManager进行逻辑验证,验证通过直接认证成功的WxAuthenticationToken,不知道出问题是否跟这个配置相关:smiling_face_with_tear:

首先 过滤器filter最先,然后到AuthenticationProvider的,你在自定义的AuthenticationProvider里面如果验证成功的话就行了。如果自定义AuthenticationProvider没有验证通过则失败。
path->filter->AuthenticationManager【provider1、provider2】

需要明确的是,你如果仅仅自定义了filter,但是没有自定义provider,那么对于security来说,是不知道你选择的哪个的,默认一般走的都是DaoAuthenticationProvider,所以最终还是会到UsernamePasswordAuthenticationFilter。

嗯嗯懂了大佬,只是我这里用WxAuthenticationManager直接继承了AuthenticationManager就不会走Provider了,验证成功,直接返回成功的WxAuthenticationToken,然后继续走后面的过滤器了。