【Spring Security】—— AuthenticationManagerBuilder

官网地址 Spring Security Reference

版本:Version 5.5.0


AuthenticationManagerBuilder 的继承关系图

在这里插入图片描述
在前面了解过 WebSecurity、HttpSecurity、AuthenticationManagerBuilder 这三个重要构建者公共的部分:

|- SecurityBuilder
	|- AbstractSecurityBuilder
		|- AbstractConfiguredSecurityBuilder

公共的这部分对构建者做扩展,点击这里可以回顾一下,这里主要看看 AuthenticationManagerBuilder 类。


ProviderManagerBuilder 接口

继承 SecurityBuilder ,也是一个构建器,它构建的对象是 AuthenticationManager(认证管理器 )。

源码注释对这个接口的说明:用于操作创建 ProviderManager 的 SecurityBuilder 的接口

它只有两个抽象方法:

  1. build() 方法继承自父类,用来构建对象(AuthenticationManager
  2. authenticationProvider(AuthenticationProvider authenticationProvider) 方法
    这个方法由子类实现,源码对这个方法的描述:
    • 根据传入的自定义 AuthenticationProvider 添加(authentication )身份验证。
    • 由于 AuthenticationProvider 实现未知,因此所有自定义都必须在外部完成并立即返回 ProviderManagerBuilder。
    • 添加过程中出错会抛异常

个人理解,这个接口对父接口扩展的主要点在于:以AuthenticationProvider的形式向构建器添加自定义的身份验证供应者,每次添加完之后会立即返回添加完身份验证供应者之后的构建器,这样就可以利用这个返回对象继续添加身份验证供应者。

这里提到的“身份验证供应者” 是根据类名起的,表示 AuthenticationProvider 。AuthenticationProvider 的具体实现在外部完成,这样构建器久不需要关注认证的具体实现,只需要关注构建“认证管理器”(AuthenticationManager)。

这里提到了一个新的类或接口,先简单了解一下它们的作用:

  • AuthenticationProvider 接口:
    表示一个类可以处理特定的身份验证实现。每一个实现类都提供一个特定的身份认证实现。
  • AuthenticationManager 接口:处理身份认证请求的认证管理器
  • ProviderManager 类:AuthenticationManager 的一个实现类,实现通过 AuthenticationProviders 列表迭代进行身份验证请求。

AuthenticationManagerBuilder

官方对这个类的概述:SecurityBuilder 用于创建 AuthenticationManager。 允许轻松地构建内存身份验证管理器、LDAP 身份验证管理器、基于 JDBC 的身份验证管理器,允许轻松地添加 UserDetailsS​​ervice 和添加 AuthenticationProvider。

在这里插入图片描述

成员变量
  1. parentAuthenticationManager 父级认证管理器
  2. authenticationProviders 存放身份验证供应者的集合(一个List)
  3. defaultUserDetailsService 默认用户信息服务,帮助获取用户数据
  4. eraseCredentials 擦除凭证
  5. eventPublisher 事件发布器
构造方法

在这里插入图片描述
调用父类 AbstractConfiguredSecurityBuilder 的构造方法,并且传入的 allowConfigurersOfSameType 值为 true ,表示创建的这个构建器支持应用同类型的配置器。构造方法接收一个后置处理器对象。

详细可参考【Spring Security】—— WebSecurity、HttpSecurity、AuthenticationManagerBuilder 构建者的共同特性

authenticationProvider 方法

这个方法是对 ProviderManagerBuilder#authenticationProvider方法的具体实现实现,用来为构建器添加身份验证供应者,并在添加完成之后立刻返回这个构建器。

在这里插入图片描述
所有添加到 AuthenticationManagerBuilder 的身份验证供应者(AuthenticationProvider)都将被存储在构建器(AuthenticationManagerBuilder)的 authenticationProviders 成员变量中。

performBuild 方法

根据之前看的父类 AbstractConfiguredSecurityBuilder 的源码,可以知道,最终的构建逻辑实现交给了子类的 performBuild 方法。

  • AbstractSecurityBuilder
    对 build 方法做了实现:对象只允许构建一次 ,并把构建工作交给子类的 doBuild 方法
  • AbstractConfiguredSecurityBuilder
    对 doBuild 方法做了实现:增加了构建过程的生命周期,提供了可以切入生命周期的两个方法,并将具体构建交给 performBuild 方法,该方法由子类实现。
@Override
protected ProviderManager performBuild() throws Exception {
	/**
	 * 先判断是否已经完成了配置:
	 * 		确保 authenticationProviders 中有 AuthenticationProvider
	 * 		或者该构建器指定了 parentAuthenticationManager 
	 */  
	if (!isConfigured()) {
		logger.debug("No authenticationProviders and no parentAuthenticationManager defined. Returning null.");
		return null;
	}
	// 创建对象: ProviderManager 是 AuthenticationManager 的一个实现类
	ProviderManager providerManager = new ProviderManager(authenticationProviders,
			parentAuthenticationManager);
	// 设置擦除凭证(在看AuthenticationManager时再细看)
	if (eraseCredentials != null) {
		providerManager.setEraseCredentialsAfterAuthentication(eraseCredentials);
	}
	// 设置事件发布(在看AuthenticationManager时再细看)
	if (eventPublisher != null) {
		providerManager.setAuthenticationEventPublisher(eventPublisher);
	}
	// 调用后置处理
	providerManager = postProcess(providerManager);
	// 返回构建的对象
	return providerManager;
}
/**
 * 根据源码的描述,这个方法同时可以确保 AuthenticationManagerBuilder 对象以及完成了配置过程
 */
public boolean isConfigured() {
	return !authenticationProviders.isEmpty() || parentAuthenticationManager != null;
}

isConfigured()官网描述

源码注解中还有一个提示:

This method does NOT ensure that the UserDetailsService is available for the getDefaultUserDetailsService() method. Note that an Exception might be thrown if an error occurs when adding the AuthenticationProvider.

  • 这个方法不确保 UserDetailsService 可用于 getDefaultUserDetailsService() 方法。(?????标记一下后面再理解 ????)
  • 如果在添加 AuthenticationProvider 过程中发生错误,会抛出异常。
一些可以快速构建身份验证管理器的方法

这几个方法都类似,通过创建一个特殊的认证配置器应用到构建器,最后返回创建的构建器,便于针对这些配置器做自定义的设置。

  1. inMemoryAuthentication 方法
    将内存身份验证添加到 AuthenticationManagerBuilder 并返回 InMemoryUserDetailsManagerConfigurer 以允许自定义内存身份验证。

  2. jdbcUserDetailsManagerConfigurer 方法
    将 JDBC 身份验证添加到 AuthenticationManagerBuilder 并返回 JdbcUserDetailsManagerConfigurer 以允许自定义 JDBC 身份验证。并且建议使用使用 Flyway 或 Liquibase 之类的工具欸管理数据库,建议SQL优化。

  3. ldapAuthenticationProviderConfigurer 方法
    将 LDAP 身份验证添加到 AuthenticationManagerBuilder 并返回 LdapAuthenticationProviderConfigurer 以允许自定义 LDAP 身份验证。

源码注解中提到:inMemoryAuthentication 方法和 jdbcUserDetailsManagerConfigurer 方法可以确保 UserDetailsS​​ervice 可用于 getDefaultUserDetailsS​​ervice() 方法【意思是说:确保 getDefaultUserDetailsS​​ervice() 方法可以获取到一个可用的 UserDetailsS​​ervice 对象​ 】,但是 ldapAuthenticationProviderConfigurer 方法不保证这一点。

处于多出都提到了这一点,所有决定立刻解决这个问题。

首先,这三个方法都调用了 apply 方法

通过 AuthenticationManagerBuilder 的源码发现一个 apply 方法:

private <C extends UserDetailsAwareConfigurer<AuthenticationManagerBuilder, ? extends UserDetailsService>> C apply(
		C configurer) throws Exception {
	this.defaultUserDetailsService = configurer.getUserDetailsService();
	return (C) super.apply(configurer);
}

这个方法的作用与父类的 apply 方法很相似,唯一多了一点:this.defaultUserDetailsService = configurer.getUserDetailsService(); ,也就是说,在将配置器引用到构建器时,会从配置器中获取 UserDetailsService 赋值给成员变量 defaultUserDetailsService ,这样就确保了构建器的 getDefaultUserDetailsS​​ervice() 方法过去到的 UserDetailsService 可用。

再搜寻上面三个方法中各种创建的配置器(***Configurer),发现除了 LdapAuthenticationProviderConfigurer 类中找不到 getUserDetailsService 方法,其他两个都有。

到这里就算理解源码之间中提到的这句话了:This method also ensure that the UserDetailsService is available for the getDefaultUserDetailsService() method.

userDetailsService 方法
public <T extends UserDetailsService> DaoAuthenticationConfigurer<AuthenticationManagerBuilder, T> userDetailsService(
		T userDetailsService) throws Exception {
	this.defaultUserDetailsService = userDetailsService;
	return apply(new DaoAuthenticationConfigurer<>(
			userDetailsService));
}

根据传入的自定义 UserDetailsS​​ervice 添加身份验证。然后返回一个 DaoAuthenticationConfigurer 以允许自定义身份验证。并且此方法还确保 UserDetailsS​​ervice 可用于 getDefaultUserDetailsS​​ervice() 方法。另外,其他的 UserDetailsS​​ervice 可能会覆盖此 UserDetailsS​​ervice 作为默认值。

其他方法

略。

总结

应用官网描述:
AuthenticationManagerBuilder用于创建AuthenticationManager。 允许轻松构建内存身份验证,LDAP身份验证,基于JDBC的身份验证,添加UserDetailsService以及添加AuthenticationProvider。

  • 6
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值