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

修改Spring Boot组件扫描包后认证异常问题咨询

解决Spring Boot集成自定义UserDetailsService时的AuthenticationProvider缺失问题

看起来你遇到的核心问题是手动声明UserDetailsService Bean打断了Spring Security自动配置的逻辑链,导致默认的DaoAuthenticationProvider没有被正确关联到你的自定义UserService上。下面详细拆解原因和解决方案:

问题根源

Spring Security的自动配置逻辑是这样的:当容器中存在UserDetailsService实例时,它会自动创建DaoAuthenticationProvider并将该实例注入进去,完成认证链路的组装。但当你手动重写userDetailsService()方法并添加@Bean注解时,相当于你接管了UserDetailsService的Bean创建,此时自动配置不会再为你自动生成对应的DaoAuthenticationProvider,最终导致登录时找不到处理UsernamePasswordAuthenticationToken的Provider。

解决方案

方案一:移除手动的UserDetailsService Bean声明(推荐)

既然你的UserService已经通过组件扫描被加载到Spring容器中,完全不需要手动暴露它的Bean。Spring Security的自动配置会自动发现这个UserDetailsService实例,并自动完成DaoAuthenticationProvider的配置。

修改后的WebSecurityConfig代码:

@Configuration
@EnableWebSecurity
class WebSecurityConfig(@Autowired val userService: UserService) extends WebSecurityConfigurerAdapter with Logging {
  protected override def configure(http: HttpSecurity): Unit = {
    http.csrf().disable().authorizeRequests()
      .antMatchers("/", "/demo").permitAll()
      .anyRequest().authenticated()
      .and()
      .formLogin()
      .loginProcessingUrl("/login")
      .permitAll()
      .and()
      .logout()
      .permitAll();
  }

  // 移除这个手动声明的@Bean方法
  // @Bean
  // override def userDetailsService: UserDetailsService = {
  //   userService
  // }
}

方案二:手动配置DaoAuthenticationProvider(如果必须声明Bean)

如果你因为某些场景需要手动暴露UserDetailsService的Bean,那么需要显式创建DaoAuthenticationProvider并将你的UserService注入进去,再配置到认证管理器中:

@Configuration
@EnableWebSecurity
class WebSecurityConfig(@Autowired val userService: UserService) extends WebSecurityConfigurerAdapter with Logging {
  protected override def configure(http: HttpSecurity): Unit = {
    // 保持原有的HTTP安全配置不变
    http.csrf().disable().authorizeRequests()
      .antMatchers("/", "/demo").permitAll()
      .anyRequest().authenticated()
      .and()
      .formLogin()
      .loginProcessingUrl("/login")
      .permitAll()
      .and()
      .logout()
      .permitAll();
  }

  @Bean
  override def userDetailsService: UserDetailsService = {
    userService
  }

  // 手动创建DaoAuthenticationProvider并关联UserDetailsService
  @Bean
  def authenticationProvider: AuthenticationProvider = {
    val provider = new DaoAuthenticationProvider()
    provider.setUserDetailsService(userDetailsService())
    // 如果你的UserService使用了自定义密码编码器,记得在这里配置
    // provider.setPasswordEncoder(passwordEncoder())
    provider
  }

  // 将自定义Provider配置到认证管理器
  override protected def configure(auth: AuthenticationManagerBuilder): Unit = {
    auth.authenticationProvider(authenticationProvider())
  }
}

对你排查现象的解释

  1. 注1现象:当只扫描UserService时,你的WebSecurityConfig没有被加载,Spring Boot会启用默认的SpringBootWebSecurityConfiguration$DefaultConfigurerAdapter,此时自动配置逻辑正常运行,DaoAuthenticationProvider被正确创建并关联到UserService。
  2. 注2现象:当强制扫描WebSecurityConfig时,你的手动UserDetailsService Bean被注册,但没有对应的AuthenticationProvider绑定它——此时UserService只是存在于容器中,但没有被任何认证组件使用,所以登录时会抛出找不到Provider的异常。

内容的提问来源于stack exchange,提问作者Doru Chiulan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 16:12:44