AuthenticationManager

AuthenticationManager,第1张

AuthenticationManager 1.了解 1.1ProviderManager

ProviderManager管理了一个AuthenticationProvider列表,每个AuthenticationProvider都是一个认证器

ProviderManager 相当于代理了多个 AuthenticationProvider,他们的关系如下图:

1.2AuthenticationProvider
public interface AuthenticationProvider {
    Authentication authenticate(Authentication var1) throws AuthenticationException;

    boolean supports(Class var1);
}

AuthenticationProvider

  • authenticate方法来验证,就是验证用户身份

  • supports用来判断当前AuthenicationProvider是否对应支持Authentication

1.3Parent
  • 一个ProviderManager管理多个AuthenticationPorvider
  • 每一个ProviderManager可以配置一个parent
  • 如果当前的 ProviderManager 中认证失败了,还可以去它的 parent 中继续执行认证(一般还是ProviderManager)

AuthenticationManager 的初始化会分为两块,

一个全局的 AuthenticationManager,也就是 parent,另一个则是局部的 AuthenticationManager。

先给大家一个结论,一个系统中,我们可以配置多个 HttpSecurity(参见Spring Security 竟然可以同时存在多个过滤器链?),而每一个 HttpSecurity 都有一个对应的 AuthenticationManager 实例(局部 AuthenticationManager),这些局部的 AuthenticationManager 实例都有一个共同的 parent,那就是全局的 AuthenticationManager。

2.源码分析

AuthenticationManagerBuilder 源码比较长,我们来看几个关键的方法

public class AuthenticationManagerBuilder
  extends
  AbstractConfiguredSecurityBuilder
  implements ProviderManagerBuilder {
 public AuthenticationManagerBuilder(ObjectPostProcessor objectPostProcessor) {
  super(objectPostProcessor, true);
 }
 public AuthenticationManagerBuilder parentAuthenticationManager(
   AuthenticationManager authenticationManager) {
  if (authenticationManager instanceof ProviderManager) {
   eraseCredentials(((ProviderManager) authenticationManager)
     .isEraseCredentialsAfterAuthentication());
  }
  this.parentAuthenticationManager = authenticationManager;
  return this;
 }
 public InMemoryUserDetailsManagerConfigurer inMemoryAuthentication()
   throws Exception {
  return apply(new InMemoryUserDetailsManagerConfigurer<>());
 }
 public JdbcUserDetailsManagerConfigurer jdbcAuthentication()
   throws Exception {
  return apply(new JdbcUserDetailsManagerConfigurer<>());
 }
 public  DaoAuthenticationConfigurer userDetailsService(
   T userDetailsService) throws Exception {
  this.defaultUserDetailsService = userDetailsService;
  return apply(new DaoAuthenticationConfigurer<>(
    userDetailsService));
 }
 @Override
 protected ProviderManager performBuild() throws Exception {
  if (!isConfigured()) {
   logger.debug("No authenticationProviders and no parentAuthenticationManager defined. Returning null.");
   return null;
  }
  ProviderManager providerManager = new ProviderManager(authenticationProviders,
    parentAuthenticationManager);
  if (eraseCredentials != null) {
   providerManager.setEraseCredentialsAfterAuthentication(eraseCredentials);
  }
  if (eventPublisher != null) {
   providerManager.setAuthenticationEventPublisher(eventPublisher);
  }
  providerManager = postProcess(providerManager);
  return providerManager;
 }
}
 

步骤分析:

1.首先,我们调用parentAuthenticationManager 给AuthenticationManager 设置parent
2.inMemoryAuthentication、jdbcAuthentication 以及 userDetailsService 几个方法是配置数据源
3.performBuild方法,根据AuthenticationManagerBuilder构建AuthenticationManager  
 构建ProviderManager,一方面传入authenticationProviders(就是ProviderManager 管理的所有AuthenticationProvider),另一方面传入ProviderManager 的 parent(其实也是一个 ProviderManager)
2.1初始化

AuthenticationConfiguration ,这个类可以当做

@Configuration(proxyBeanMethods = false)
@import(ObjectPostProcessorConfiguration.class)
public class AuthenticationConfiguration {
 @Bean
 public AuthenticationManagerBuilder authenticationManagerBuilder(
   ObjectPostProcessor objectPostProcessor, ApplicationContext context) {
  LazyPasswordEncoder defaultPasswordEncoder = new LazyPasswordEncoder(context);
  AuthenticationEventPublisher authenticationEventPublisher = getBeanOrNull(context, AuthenticationEventPublisher.class);

  DefaultPasswordEncoderAuthenticationManagerBuilder result = new DefaultPasswordEncoderAuthenticationManagerBuilder(objectPostProcessor, defaultPasswordEncoder);
  if (authenticationEventPublisher != null) {
   result.authenticationEventPublisher(authenticationEventPublisher);
  }
  return result;
 }

 @Bean
 public static GlobalAuthenticationConfigurerAdapter enableGlobalAuthenticationAutowiredConfigurer(
   ApplicationContext context) {
  return new EnableGlobalAuthenticationAutowiredConfigurer(context);
 }

 @Bean
 public static InitializeUserDetailsBeanManagerConfigurer initializeUserDetailsBeanManagerConfigurer(ApplicationContext context) {
  return new InitializeUserDetailsBeanManagerConfigurer(context);
 }

 @Bean
 public static InitializeAuthenticationProviderBeanManagerConfigurer initializeAuthenticationProviderBeanManagerConfigurer(ApplicationContext context) {
  return new InitializeAuthenticationProviderBeanManagerConfigurer(context);
 }

 public AuthenticationManager getAuthenticationManager() throws Exception {
  if (this.authenticationManagerInitialized) {
   return this.authenticationManager;
  }
  AuthenticationManagerBuilder authBuilder = this.applicationContext.getBean(AuthenticationManagerBuilder.class);
  if (this.buildingAuthenticationManager.getAndSet(true)) {
   return new AuthenticationManagerDelegator(authBuilder);
  }

  for (GlobalAuthenticationConfigurerAdapter config : globalAuthConfigurers) {
   authBuilder.apply(config);
  }

  authenticationManager = authBuilder.build();

  if (authenticationManager == null) {
   authenticationManager = getAuthenticationManagerBean();
  }

  this.authenticationManagerInitialized = true;
  return authenticationManager;
 }

 @Autowired
 public void setApplicationContext(ApplicationContext applicationContext) {
  this.applicationContext = applicationContext;
 }

 @Autowired
 public void setObjectPostProcessor(ObjectPostProcessor objectPostProcessor) {
  this.objectPostProcessor = objectPostProcessor;
 }

 private static class EnableGlobalAuthenticationAutowiredConfigurer extends
   GlobalAuthenticationConfigurerAdapter {
  private final ApplicationContext context;
  private static final Log logger = LogFactory
    .getLog(EnableGlobalAuthenticationAutowiredConfigurer.class);

  EnableGlobalAuthenticationAutowiredConfigurer(ApplicationContext context) {
   this.context = context;
  }

  @Override
  public void init(AuthenticationManagerBuilder auth) {
   Map beansWithAnnotation = context
     .getBeansWithAnnotation(EnableGlobalAuthentication.class);
   if (logger.isDebugEnabled()) {
    logger.debug("Eagerly initializing " + beansWithAnnotation);
   }
  }
 }
}
 

一言以蔽之,AuthenticationConfiguration 中的配置有没有用上,全看开发者有没有重写 configure(AuthenticationManagerBuilder auth) 方法,重写了,就用 localConfigureAuthenticationBldr 来构建 parent 级别的 AuthenticationManager,没重写,就用 AuthenticationConfiguration 中的方法来构建。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5660096.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-16
下一篇 2022-12-16

发表评论

登录后才能评论

评论列表(0条)