【问题标题】:Spring security custom filter (reason for creating AuthenticationManager bean while it already exists)Spring 安全自定义过滤器(在 AuthenticationManager bean 已经存在时创建它的原因)
【发布时间】:2021-12-09 19:42:05
【问题描述】:

当我们使用自定义过滤器时,我们需要注入 AuthenticationManager 类型的 bean。

据我所知,如果我们使用默认过滤器,那么 Spring 会自动提供身份验证管理器。这使我得出结论,在 Spring 上下文中已经有一个 AuthenticationManager bean(根据我的理解)。

但问题是我的假设不正确。我必须创建一个 AuthenticationManager 的 bean 并将其注入过滤器。

我的假设有什么问题?为什么我们需要在 bean 已经存在的时候将其打包?

【问题讨论】:

    标签: java spring spring-boot spring-security servlet-filters


    【解决方案1】:

    Spring 使用AuthenticationManager 来查找合适的身份验证提供程序,但默认情况下没有将AuthenticationManager 注册为bean。查看HttpSecurityConfiguration类的源码。

    @Bean(HTTPSECURITY_BEAN_NAME)
    @Scope("prototype")
    HttpSecurity httpSecurity() throws Exception {
        WebSecurityConfigurerAdapter.LazyPasswordEncoder passwordEncoder = new WebSecurityConfigurerAdapter.LazyPasswordEncoder(
                this.context);
        AuthenticationManagerBuilder authenticationBuilder = new WebSecurityConfigurerAdapter.DefaultPasswordEncoderAuthenticationManagerBuilder(
                this.objectPostProcessor, passwordEncoder);
        authenticationBuilder.parentAuthenticationManager(authenticationManager());
        HttpSecurity http = new HttpSecurity(this.objectPostProcessor, authenticationBuilder, createSharedObjects());
        // @formatter:off
        http
            .csrf(withDefaults())
            .addFilter(new WebAsyncManagerIntegrationFilter())
            .exceptionHandling(withDefaults())
            .headers(withDefaults())
            .sessionManagement(withDefaults())
            .securityContext(withDefaults())
            .requestCache(withDefaults())
            .anonymous(withDefaults())
            .servletApi(withDefaults())
            .apply(new DefaultLoginPageConfigurer<>());
        http.logout(withDefaults());
        // @formatter:on
        return http;
    }
    
    private AuthenticationManager authenticationManager() throws Exception {
        return (this.authenticationManager != null) ? this.authenticationManager
                : this.authenticationConfiguration.getAuthenticationManager();
    }
    

    如您所见,它在HttpSecurity 中注册了一个身份验证管理器构建器。稍后在HttpSecurity 类中,它将使用此构建器来构建身份验证管理器并将其注册到共享对象中[参见HttpSecurity 中的beforeConfigure() 方法]。

    @Override
    protected void beforeConfigure() throws Exception {
        setSharedObject(AuthenticationManager.class, getAuthenticationRegistry().build());
    }
    

    并且每当需要身份验证管理器时,它都会使用HttpSecurity 来获得它,如下所示:

    AuthenticationManager authenticationManager = http.getSharedObject(AuthenticationManager.class);
    

    【讨论】:

    • 非常感谢。你是救生员。
    猜你喜欢
    • 2019-12-16
    • 2016-03-17
    • 2021-01-02
    • 2015-05-30
    • 2017-03-13
    • 1970-01-01
    • 2016-12-20
    • 2023-03-05
    • 1970-01-01
    相关资源
    最近更新 更多