You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Security升级后如何向自定义Filter注入AuthenticationManager

问题根源

当前写法存在两个核心问题:

  1. 在securityFilterChain方法内部直接调用同配置类下的authenticationManager()方法获取实例,不会走Spring Bean代理逻辑,容易拿到未完成初始化的AuthenticationManager对象,甚至触发循环依赖。
  2. 手动通过new关键字实例化自定义Filter时,这些实例不归Spring容器管理,类内部的@Value属性注入会直接失效,后续注入其他Spring管理组件也会报错。

另外现有配置还有两个额外的bug:

  • 权限匹配规则顺序错误:Spring Security按配置从上到下的顺序执行匹配,你把/**全放行规则放在权限校验规则前面,会导致后续的ADMIN权限校验、登录校验规则完全不生效,范围越大的匹配规则需要放在越靠后的位置。
  • 注册接口路径存在笔误:/users//register多写了一个斜杠,实际匹配会和预期路径不一致。
正确实现方案

方案一:从HttpSecurity上下文获取已初始化的AuthenticationManager(推荐)

Spring Security构建HttpSecurity时,已经将初始化完成的AuthenticationManager存入上下文共享对象,不需要手动调用Bean方法获取,直接修改配置即可:

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    // 直接从HttpSecurity共享对象中拿可用的AuthenticationManager实例
    AuthenticationManager authManager = http.getSharedObject(AuthenticationManager.class);

    http.csrf().disable()
            .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            .and()
            .addFilter(new CustomAuthenticationFilter(authManager))
            .addFilter(new CustomAuthorizationFilter(authManager, userRepository))
            .authorizeRequests()
            .antMatchers(HttpMethod.POST, "/user/users/save", "/login", "/users/register").permitAll()
            .antMatchers("/user/**").hasAuthority("ADMIN")
            .antMatchers("/user/**").authenticated()
            .antMatchers("/**").permitAll(); // 测试用全放行规则移到最后
    return http.build();
}

这种写法不需要改动自定义Filter的现有代码,改动量最小。

方案二:将自定义Filter交给Spring容器管理

如果后续需要在自定义Filter中使用更多Spring注入的组件,可以把Filter声明为Spring Bean,直接通过容器注入依赖:

  1. 修改CustomAuthenticationFilter,加上Spring注解,用构造器注入所有依赖:
@Component
public class CustomAuthenticationFilter extends UsernamePasswordAuthenticationFilter {

    private final AuthenticationManager authenticationManager;
    private final String secretKey;

    // 所有依赖直接通过构造器注入,不需要字段注入
    public CustomAuthenticationFilter(AuthenticationManager authenticationManager, @Value("${security.key}") String secretKey) {
        this.authenticationManager = authenticationManager;
        this.secretKey = secretKey;
    }

    // attemptAuthentication、successfulAuthentication方法逻辑保持原有写法即可
}
  1. 对CustomAuthorizationFilter做同样改造,通过构造器注入AuthenticationManager和UserRepository,加上@Component注解。
  2. 修改SecurityConfig,直接注入两个Filter实例加入过滤链:
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http,
                                               CustomAuthenticationFilter authFilter,
                                               CustomAuthorizationFilter authorizationFilter) throws Exception {
    http.csrf().disable()
            .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            .and()
            .addFilter(authFilter)
            .addFilter(authorizationFilter)
            .authorizeRequests()
            .antMatchers(HttpMethod.POST, "/user/users/save", "/login", "/users/register").permitAll()
            .antMatchers("/user/**").hasAuthority("ADMIN")
            .antMatchers("/user/**").authenticated()
            .antMatchers("/**").permitAll();
    return http.build();
}

注意:Spring Boot默认会将@Component标注的Filter自动注册到全局Servlet过滤链,可能导致过滤器重复执行。如果遇到重复触发的问题,添加如下配置关闭自动注册即可:

@Bean
public FilterRegistrationBean<CustomAuthenticationFilter> authFilterRegistration(CustomAuthenticationFilter filter) {
    FilterRegistrationBean<CustomAuthenticationFilter> registration = new FilterRegistrationBean<>(filter);
    registration.setEnabled(false);
    return registration;
}
@Bean
public FilterRegistrationBean<CustomAuthorizationFilter> authorizationFilterRegistration(CustomAuthorizationFilter filter) {
    FilterRegistrationBean<CustomAuthorizationFilter> registration = new FilterRegistrationBean<>(filter);
    registration.setEnabled(false);
    return registration;
}

内容的提问来源于stack exchange,提问作者Elen Mouradian

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.31 04:18:22