【问题标题】:Authentication manager is null after upgrading spring security升级spring security后认证管理器为空
【发布时间】:2022-12-22 13:40:25
【问题描述】:

我正在用spring boot2.7.4版本编写应用程序,其中包含spring security的新版本。所以我需要将旧代码重写为新代码。 这是我的旧安全配置 WebSecurityConfigurerAdapter

@Configuration
@EnableWebSecurity
class AppWebConfig(
    val customUserDetailsService: CustomUserDetailsService,
    val passwordEncoder: PasswordEncoder,
    val tokensService: TokensService
) : WebSecurityConfigurerAdapter() {

    @Throws(Exception::class)
    override fun configure(auth: AuthenticationManagerBuilder) {
        auth
            .userDetailsService(customUserDetailsService)
            .passwordEncoder(passwordEncoder)
    }

    @Throws(Exception::class)
    override fun configure(http: HttpSecurity) {
        http
            .cors()
            .and()
            .csrf().disable()
            .exceptionHandling()
            //urls permissions...
            .addFilter(AppAuthorizationFilter(authenticationManager(), tokensServicee))
    }

}

这是新代码

@Configuration
@EnableWebSecurity
class AppWebConfig(
    val tokensService: TokensService,
) {

    @Bean
    @Throws(Exception::class)
    fun authenticationManager(authenticationConfiguration: AuthenticationConfiguration): AuthenticationManager? {
        return authenticationConfiguration.authenticationManager
    }

    @Bean
    @Throws(Exception::class)
    protected fun fitlerChain(http: HttpSecurity): SecurityFilterChain {
        val authenticationManager = http.getSharedObject(AuthenticationManager::class.java)

        return http
            .cors()
            .and()
            .csrf().disable()
            //urls permissions...
            .addFilter(AppAuthorizationFilter(authenticationManager, tokensService))
            .build()
    }

这是 AppAuthorizationFilter,它在两个版本中都没有改变,并且使用了 authenticationManager

class AppAuthorizationFilter(
    authenticationManager: AuthenticationManager,
    tokensService: TokensService,
) : BasicAuthenticationFilter(authenticationManager) {
    private val tokensService: TokensService

    init { this.tokensService = tokensService }

    @Throws(IOException::class, ServletException::class)
    override fun doFilterInternal(
        request: HttpServletRequest,
        response: HttpServletResponse,
        chain: FilterChain,
    ) {
        val header = request.getHeader(Objects.requireNonNull(HttpHeaders.AUTHORIZATION))
        if (header != null) {
            val authorizedUser = tokensService.parseAccessToken(header)
            SecurityContextHolder.getContext().authentication = authorizedUser
        }
        chain.doFilter(request, response)
    }
}

问题出在来自AppWebConfigauthenticationManager。我得到的错误是它为空。

Caused by: java.lang.NullPointerException: authenticationManager must not be null at com.app.security.config.WebConfig.fitlerChain(WebConfig.kt:68)

我通过从共享对象 http.getSharedObject(AuthenticationManager::class.java) 中获取 authenticationManager 来尝试上面显示的解决方案,但如您所见,它不起作用。

我通过从 WebApplicationContext 获取 authenticationManager 解决了这个问题,但我不确定这是否是最好的方法

val authenticationManager = applicationContext.getBean("authenticationManager") as AuthenticationManager

【问题讨论】:

    标签: spring spring-boot kotlin spring-security


    【解决方案1】:

    尝试将此注释 (@Primary) 添加到您的 authenticationManager bean。如果不起作用,请使用您提到的解决方案。

    @Bean
    @Primary // try to add this
    @Throws(Exception::class)
    fun authenticationManager(authenticationConfiguration: AuthenticationConfiguration): AuthenticationManager? {
        return authenticationConfiguration.authenticationManager
    }
    

    【讨论】:

      【解决方案2】:

      请在构建后或构建后访问身份验证管理器。

             public SecurityFilterChain securityFilterChain(HttpSecurity http, ResourceProtectAware protectAware) throws Exception {
                  protectAware.addUrlAuthorization(http);
                  http.cors();
                  http.httpBasic().authenticationEntryPoint(entryPoint());
                 // http.addFilterBefore(spnegoAuthenticationFilter(configuration.getAuthenticationManager()), BasicAuthenticationFilter.class);
                  DefaultSecurityFilterChain build = http.build();
      //access it after you build. 
                  AuthenticationManager sharedObject = http.getSharedObject(AuthenticationManager.class);
                  return build;
              }
      

      【讨论】:

        猜你喜欢
        • 2012-05-01
        • 1970-01-01
        • 2015-10-14
        • 2014-11-09
        • 2021-08-30
        • 2016-04-29
        • 1970-01-01
        • 2017-07-15
        • 1970-01-01
        相关资源
        最近更新 更多