spring security authority(在Spring Security中如何获取AuthenticationManager对象?)
有时需要使用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()方法的源码 。
可以发现在该方法中使用Adapter类的私有字段authenticationConfiguration的getAuthenticationManager()方法获取Manager对象 。而字段authenticationConfiguration是使用方法setAthenticationConfiguration()自动注入的 ,所以Spring的Bean库中存在Manager对象 。由此可得到如下获取AuthenticationManager对象的方案一 。
方案一:从Spring的Bean库中获取AuthenticationConfiguration(以下简称Configuration)对象 ,然后使用Configuration对象的getAuthenticationManager()方法获取Manager对象 。(关于如何从Spring中获取Bean ,本文不作介绍 ,请读者自行查阅资料了解)
继续查看Configuration#getAuthenticationManager()方法的源码 。
源码中展示的流程如下 。
① 如果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对象 。
⑤ 如果尚未使用Builder对象构建Manager对象 ,则先把Configuration的私有字段globalAuthConfigurers的数据应用在Builder对象上(私有字段globalAuthConfigurers是通过方法setGlobalAuthConfigurers()自动注入的)。
⑥ 然后使用Builder对象的build()方法构建Manager对象 。
⑦ 在Builder#build()方法中 ,第一次调用该方法会使用doBuild()方法生成Manager对象(不分析doBuild()方法) ,并将这个对象缓存下来 。以后再调用build()方法将会抛出AlreadyBuiltException异常 。也就是说可以从Spring的Bean库中获取Builder对象 ,然后用它的build()方法获得Manager对象 。
⑧ 如果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对象对象做了处理 ,而方案二并没有做这种处理 ,推荐使用方案一 。
创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!