Spring Security中如何获取AuthenticationManager对象

 更新时间:2022年11月25日 08:26:36   作者:Halloworlds  
有时需要使用AuthenticationManager(以下简称Manager)对象,可是这个对象不是Bean,没有直接保存在Spring的Bean库中,那么如何获取Spring Security中的这个对象呢,需要的朋友可以参考下

有时需要使用AuthenticationManager(以下简称Manager)对象,可是这个对象不是Bean,没有直接保存在Spring的Bean库中。那么如何获取Spring Security中的这个对象呢?

在Spring Security 5.7.0-M2之前,通常会扩展WebSecurityConfigurerAdapter(以下简称Adapter)类来自定义网络安全配置。Adapter类中有一个方法authenticationManager()可以提供Manager对象。但是从Spring Security 5.7.0-M2开始,Adapter类就被弃用,再用此类中的authenticationManager()方法获取Manager对象就不合适了。

以下是Adapter#authenticationManager()方法的源码。

protected AuthenticationManager authenticationManager() throws Exception {
    if (!this.authenticationManagerInitialized) {
        configure(this.localConfigureAuthenticationBldr);
        if (this.disableLocalConfigureAuthenticationBldr) {
            this.authenticationManager = this.authenticationConfiguration.getAuthenticationManager();
        } else {
            this.authenticationManager = this.localConfigureAuthenticationBldr.build();
    }
    this.authenticationManagerInitialized = true;
    }
    return this.authenticationManager;
}

可以发现在该方法中使用Adapter类的私有字段authenticationConfiguration的getAuthenticationManager()方法获取Manager对象。而字段authenticationConfiguration是使用方法setAthenticationConfiguration()自动注入的,所以Spring的Bean库中存在Manager对象。由此可得到如下获取AuthenticationManager对象的方案一。

方案一:从Spring的Bean库中获取AuthenticationConfiguration(以下简称Configuration)对象,然后使用Configuration对象的getAuthenticationManager()方法获取Manager对象。(关于如何从Spring中获取Bean,本文不作介绍,请读者自行查阅资料了解)

继续查看Configuration#getAuthenticationManager()方法的源码。

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 : this.globalAuthConfigurers) {
        authBuilder.apply(config);
    }
    this.authenticationManager = authBuilder.build();
    if (this.authenticationManager == null) {
        this.authenticationManager = getAuthenticationManagerBean();
    }
    this.authenticationManagerInitialized = true;
    return this.authenticationManager;
}

源码中展示的流程如下。

① 如果Configuration对象中已保存有Manager对象,则返回该对象。

② 如果Configuration对象中没有Manager对象,则从Spring的Bean库中获取AuthenticationManagerBuilder(以下简称Builder)对象。

③ 如果已经用Builder对象构建了Manager对象,则返回一个使用Builder对象初始化的AuthenticationManagerDelegator对象。

④ AuthenticationManagerDelegator是Manager的子类。该类代理了另一个Manager对象,被代理的Manager对象是使用Builder对象的getObject()方法获得的。Builder#getObject()的代码表明,在调用该方法前,需要先在Builder对象内构建一个Manager。也就是说可以从Spring的Bean库中获取Builder对象,然后用它的getObject()方法获得Manager对象。

@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
    if (this.delegate != null) {
        return this.delegate.authenticate(authentication);
    }
    synchronized (this.delegateMonitor) {
        if (this.delegate == null) {
            this.delegate = this.delegateBuilder.getObject();
            this.delegateBuilder = null;
        }
    }
    return this.delegate.authenticate(authentication);
}

⑤ 如果尚未使用Builder对象构建Manager对象,则先把Configuration的私有字段globalAuthConfigurers的数据应用在Builder对象上(私有字段globalAuthConfigurers是通过方法setGlobalAuthConfigurers()自动注入的)。

⑥ 然后使用Builder对象的build()方法构建Manager对象。

⑦ 在Builder#build()方法中,第一次调用该方法会使用doBuild()方法生成Manager对象(不分析doBuild()方法),并将这个对象缓存下来。以后再调用build()方法将会抛出AlreadyBuiltException异常。也就是说可以从Spring的Bean库中获取Builder对象,然后用它的build()方法获得Manager对象。

@Override
public final O build() throws Exception {
    if (this.building.compareAndSet(false, true)) {
        this.object = doBuild();
        return this.object;
    }
    throw new AlreadyBuiltException("This object has already been built");
}

⑧ 如果Builder对象未能成功构建Manager对象,则使用Configuration的私有方法lazyBean()方法获取Manager对象(不分析lazyBean()方法)。

上述流程表明,可以从Spring的Bean库中获取AuthenticationManagerBuilder对象,然后使用该对象的build()方法或getObject()方法获取AuthenticationManager对象。获取AuthenticationManager对象的方案二如下。

方案二:从Spring的Bean库中获取AuthenticationManagerBuilder对象,首先调用该对象的build()方法获取Manager对象,并对方法调用捕获AlreadyBuiltException异常。若捕获到异常,则在异常处理代码中调用Builder对象的getObject()方法获取Manager对象。

方案二可能有缺陷。在Configuration#getAuthenticationManager()方法的源码中可以看到步骤⑤对Builder对象对象做了处理,而方案二并没有做这种处理,推荐使用方案一。

到此这篇关于在Spring Security中如何获取AuthenticationManager对象的文章就介绍到这了,更多相关Spring Security 获取AuthenticationManager对象内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • java学习之JVM运行时常量池理解

    java学习之JVM运行时常量池理解

    这篇文章主要介绍了java学习之JVM运行时常量池理解,对常量池的好处以及基本类型的包装类常量池等作了简要分析,有需要的朋友可以借鉴参考下
    2021-09-09
  • java公众平台通用接口工具类HttpConnectUtil实例代码

    java公众平台通用接口工具类HttpConnectUtil实例代码

    下面小编就为大家分享一篇java公众平台通用接口工具类HttpConnectUtil实例代码,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-01-01
  • 通过实例了解java序列化机制

    通过实例了解java序列化机制

    这篇文章主要介绍了通过实例了解java序列化机制,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-11-11
  • 详解Java包装类及自动装箱拆箱

    详解Java包装类及自动装箱拆箱

    这篇文章主要介绍了Java包装类及自动装箱拆箱,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-03-03
  • 详解Java的Hibernate框架中的注解与缓存

    详解Java的Hibernate框架中的注解与缓存

    这篇文章主要介绍了详解Java的Hibernate框架中的注解与缓存,Hibernate是Java的SSH三大web开发框架之一,需要的朋友可以参考下
    2015-12-12
  • Java集合List和Map互转的方法总结

    Java集合List和Map互转的方法总结

    有时候我们需要将给定的List转换为Map,或者Map转换为List,本文主要介绍了Java集合List和Map互转的方法总结,具有一定的参考价值,感兴趣的可以了解一下
    2023-09-09
  • 阿里的Easyexcel读取Excel文件的方法(最新版本)

    阿里的Easyexcel读取Excel文件的方法(最新版本)

    这篇文章主要介绍了阿里的Easyexcel读取Excel文件(最新版本)的方法,本文通过示例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-12-12
  • springboot集成测试最小化依赖实践示例

    springboot集成测试最小化依赖实践示例

    这篇文章主要为大家介绍了springboot集成测试最小化依赖实践示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-06-06
  • java -jar指定外部配置文件操作步骤

    java -jar指定外部配置文件操作步骤

    这篇文章主要给大家介绍了关于java -jar指定外部配置文件的相关资料,需要的朋友可以参考下
    2023-11-11
  • 详解Java ThreadPoolExecutor的拒绝策略

    详解Java ThreadPoolExecutor的拒绝策略

    这篇文章主要介绍了Java ThreadPoolExecutor的拒绝策略,本文对于线程的池的几种策略进行详细的讲解,在实际的生产中需要集合相关的场景来选择合适的拒绝策略,需要的朋友可以参考下
    2022-08-08

最新评论