SpringSecurity(十):全局AuthenticationManager与局部AuthenticationManager

在之前的分析中我们已经知道了Spring Security是由AuthenticationManager(ProviderManager)把认证请求分发给多个认证器。

在Spring Security中存在全局AuthenticationManager与局部AuthenticationManager两种

我们先来看下面代码:

public class SecurityConfig extends WebSecurityConfigurerAdapter{
@Override
protected void configure(HttpSecurity http) throws Exception{

//简单定义一个基于内存的UserDetailsService实例 作为示范
InMemoryUserDetailsManager users=new InMemoryUserDetailsManager();
users.createUser(User.withUsername("javaboy").password("{noop}123456").roles("admin").build());

http.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.permitAll()
.and()
.userDetailsService(users)
.csrf().disable();
}
}

此时我们虽然配置了UserDetailsService,但是我们发现使用 Spring Security生成的用户 仍能登录!

原因很简单,因为此时我们注册的是一个局部AuthenticationManager,系统仍会生成一个全局AuthenticationManager(AuthenticationConfiguration的getAuthenticationManager方法),全局AuthenticationManager会从Spring容器中寻找UserDetailsService实例,由于我们也没有往容器中注入UserDetailsService实例,因此会使用系统提供的实例!

虽然在实际使用中对我们没有太大的影响,因为Spring Security会先使用局部AuthenticationManager进行认证,再使用全局AuthenticationManager进行认证。但如果我们想要直接修改全局AuthenticationManager的话,有两种思路:
(一)直接生成全局AuthenticationManager
(二)往Spring容器中注入UserDetailsService实例

先说第一种,生成全局AuthenticationManager只需要重写configure(AuthenticationManagerBuilder auth)方法

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter{
@Autowired
UserDateService userDateService;

//注意是参数为AuthenticationManagerBuilder的configure方法
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception{
auth.userDetailsService(userDateService);

}
....

}

往Spring容器中注入UserDetailsService实例更简单,只需要加一个@Bean注解即可!

需要注意的是,一旦我们重写了configure(AuthenticationManagerBuilder auth)方法,则使用的UserDetailsService实例 则是 方法中注入的实例,此时容器中的UserDetailsService实例将不起作用!(AuthenticationConfiguration的getAuthenticationManager方法没有被调用!)

上一篇:Spring Boot MyBatis Sql拦截器(自定义注解+反射)


下一篇:Spring Security Config : 被AuthenticationManagerBuilder的各种安全配置器