Spring 安全性:其他bean可以访问全局AuthenticationManagerBuilder吗?

Spring Security: Can other beans access the global AuthenticationManagerBuilder?

我已经设置了样板 spring 安全配置器:

public class SecurityConfiguration extends WebSecurityConfigurerAdapter {


@Autowired
private DataSource datasource;

@Override
protected void configure(HttpSecurity http) throws Exception {
   // ...setting up security for routes, etc.
}

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception { 
      // here I have access to the AuthenticationManagerBuilder
      // I can associate it with my datasource, set the password encoder, etc.
 JdbcUserDetailsManager userDetailsService = new   JdbcUserDetailsManager();
    userDetailsService.setDataSource(datasource);
    PasswordEncoder encoder = new BCryptPasswordEncoder();
auth.userDetailsService(userDetailsService).passwordEncoder(encoder);
    auth.jdbcAuthentication().dataSource(datasource);

}

但我想要的是能够像这样从另一个 bean 访问 AuthenticationManagerBuilder:

@Service
public class MyUserService {

@Autowired
AuthenticationManagerBuilder builder; 

public void createUser(...) {
//use builder here...
    JdbcUserDetailsManager userDetailsService = new JdbcUserDetailsManager();
    userDetailsService.setDataSource(datasource);
    PasswordEncoder encoder = new BCryptPasswordEncoder();
    builder.userDetailsService(userDetailsService)
      .passwordEncoder(encoder);
    builder.jdbcAuthentication().dataSource(datasource);
    userDetailsService.createUser(new User(...));
}

是否有任何方法可以从其他 bean 访问自动传递给 configure() 方法的相同 AuthenticationManagerBuilder 实例?

AuthenticationManagerBuilder 实际上仅用于构建您的身份验证对象(即 UserDetails、AuthenticationProvider、AuthenticationManager)。它不适用于应用程序本身。

相反,我建议使用 UserDetailsManager API。您可以创建一个 UserDetailsManager Bean,将 UserDetailsManager 提供给 AuthenticationManagerBuilder 以创建 AuthenticationProvider 和 AuthenticationManager,然后您可以直接在代码中使用 UserDetailsManager。

像这样:

@EnableWebMvcSecurity
@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
    ...

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth, UserDetailsService uds) throws Exception { 
      auth
        .userDetailsService(uds)
        .passwordEncoder(new BCryptPasswordEncoder());
    }

    @Bean
    public UserDetailsManager udm(DataSource dataSource) {
        JdbcUserDetailsManager udm = new JdbcUserDetailsManager();
        udm.setDataSource(dataSource);
        return udm;
    }
}

@Service
public class MyUserService {

    @Autowired
    UserDetailsManager udm; 

    public void createUser(...) {
        //use builder here...
        udm.createUser(new User(...));
    }
}

需要注意的一件事是我们利用了 AuthenticationManagerBuilder 的全局实例。为了确保在构建 AuthenticationProvider 和 AuthenticationManager 之前调用 configureGlobal 方法,您需要在配置上添加 EnableGlobalAuthentication、EnableWebMvcSecurity 或 EnableWebSecurity 注释 class(我们的示例已经这样做了)。