spring-security 由于WebSecurityConfigurerAdapter已弃用,Spring获取AuthenticationManager示例变得复杂

pw9qyyiw  于 2022-11-11  发布在  Spring
关注(0)|答案(1)|浏览(1052)

Spring最近弃用了WebSecurityConfigurerAdapter,这看起来并不是最明智的举动,因为新方法的文档记录非常糟糕,而且WebSecurityConfigurerAdapter基本上无处不在。现在我尝试向安全过滤器链添加一个自定义过滤器,这在以前很容易,但现在看起来确实带来了一些麻烦。
我找到了一个变通方法,但感觉非常复杂,甚至没有远程文档记录。如果我使用类似下面的代码,我确实得到了authenticationManager的一个示例,一切都工作正常。

public static class MyCustomDsl extends AbstractHttpConfigurer<MyCustomDsl, HttpSecurity> {

        @Override
        public void configure(HttpSecurity http) throws Exception {
            AuthenticationManager authenticationManager =
                    http.getSharedObject(AuthenticationManager.class);
            AuthFilter filter = new AuthFilter();
            filter.setAuthenticationManager(authenticationManager);
            System.out.println("Manager is" + authenticationManager); 
// prints Manager is ProviderManager as expected

            http.addFilter(filter);

        }

        public static MyCustomDsl customDsl() {
            return new MyCustomDsl();
        }
    }

如果我把完全相同的代码从这个不必要的结构中直接移到下面的部分,那么它就不起作用了。我得到的错误是认证管理器为空。我确实假设它与创建Bean的时间有关,但似乎找不到比上面的解决方案更清晰的解决方案。

@Bean
    SecurityFilterChain filterChain(HttpSecurity http) throws Exception{
AuthenticationManager authenticationManager =
                http.getSharedObject(AuthenticationManager.class);
        AuthFilter filter = new AuthFilter();
        filter.setAuthenticationManager(authenticationManager);

        System.out.println("Manager is" + authenticationManager);
// says: Manager is null

//more config

}

我可能会补充一点,还有另一个奇怪的行为。我试图构建这样的示例(看起来很直观)。

AuthenticationManager authenticationManager = authenticationManagerBuilder.build();

然而,这并不奏效,更奇怪的是:如果我说build()--它会错误地显示“已经构建”。如果我试图获取它(因为它看起来已经构建了)--我会得到一个空对象。甚至还有一个getorbuild方法,但你猜对了,它也会错误。对我来说很奇怪。
我真的很感激,如果任何人可以钉我在正确的方向得到这个干净和简洁。谢谢。

xpszyzbs

xpszyzbs1#

In this post它说:
要创建可用于整个应用程序的AuthenticationManager,只需将AuthenticationManager注册为@Bean即可。
也就是说,如果你需要在某个地方使用AuthenticationManager,你需要把它公开为一个bean。我假设你已经有了UserDetailsServicePasswordEncoder bean。你可以这样做:

@Bean
AuthenticationManager myAuthenticationManager(UserDetailsService userDetailsService, PasswordEncoder passwordEncoder) {
    DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
    provider.setUserDetailsService(userDetailsService);
    provider.setPasswordEncoder(passwordEncoder);
    return provider::authenticate;
}

现在,只需将它注入到SecurityFilterChain方法中:

@Bean
SecurityFilterChain filterChain(HttpSecurity http, AuthenticationManager authenticationManager) throws Exception {
    ...
}

请注意AuthenticationProvider接口will be deprecated soon,请继续关注未来版本的发行说明。

相关问题