Spring Security 實戰乾貨:分佈式對象SharedObject

1. 前言

上一篇咱們對AuthenticationManager的初始化的細節進行了分析,其中裏面有一段代碼引發了很多同窗的注意:html

ApplicationContext context = http.getSharedObject(ApplicationContext.class);
    CaptchaAuthenticationProvider captchaAuthenticationProvider = context.getBean("captchaAuthenticationProvider", CaptchaAuthenticationProvider.class);

上面直接從HttpSecurity對象中獲取到Spring的應用上下文對象ApplicationContext,它是怎麼作到的呢?SharedObject又是個什麼概念?今天就來搞清楚這個問題。java

2. SharedObject

Spring SecuritySharedObject既不是對象也不是接口,而是某一類「可共享」的對象的統稱。編程

顧名思義,SharedObject的意思是可共享的對象。它的做用是若是一些對象你但願在不一樣的做用域配置中共享它們就把這些對象變成SharedObject,有點分佈式對象的感受。爲了更加便於你理解,下面是相關的體系結構:架構

配置類的組織架構

AbstractConfiguredSecurityBuilder或者HttpSecurityBuilder的實現類才具備操做SharedObject的能力。一種是註冊SharedObject,另外一種是獲取SharedObject分佈式

SharedObject的註冊

SharedObject會以其Class類型爲Key,實例爲Value存儲到一個HashMap<Class<?>,Object>中,具體可看HttpSecurity源碼。它的註冊分爲兩個部分,第一是HttpSecurity初始化的時候裝配進去的。咱們來看看:ide

注入AuthenticationManagerBuilder

咱們熟知的AuthenticationManagerBuilder在這裏被共享。性能

還有一部分是在全部的HttpSecurityBuilder對象初始化時註冊的。它初始化和配置都是由SecurityConfigurer來完成的:ui

public interface SecurityConfigurer<O, B extends SecurityBuilder<O>> {
 
   void init(B builder) throws Exception;
 
   void configure(B builder) throws Exception;
}

上面兩個方法分別用來初始化和配置HttpSecurityBuilder。好比咱們熟知的WebSecurityConfigurerAdapter就是用來配置HttpSecurity的,在其init方法中咱們能夠找到相關的代碼:this

private Map<Class<?>, Object> createSharedObjects() {
   Map<Class<?>, Object> sharedObjects = new HashMap<>();
   sharedObjects.putAll(localConfigureAuthenticationBldr.getSharedObjects());
   sharedObjects.put(UserDetailsService.class, userDetailsService());
   sharedObjects.put(ApplicationContext.class, context);
   sharedObjects.put(ContentNegotiationStrategy.class, contentNegotiationStrategy);
   sharedObjects.put(AuthenticationTrustResolver.class, trustResolver);
   return sharedObjects;
}

這也是我在文章開頭能夠獲取到ApplicationContext的根本緣由。code

SharedObject的獲取和使用

咱們能獲取到哪些被標記爲SharedObject類呢?SecurityConfigurer有不少實現,這些實現都是用來配置一些特定的同認證受權相關的功能的。好比OAuth2ClientConfigurer用來配置OAuth2客戶端的,它裏面就將經常使用的一些對象設置爲SharedObject

public OAuth2ClientConfigurer<B> clientRegistrationRepository(ClientRegistrationRepository clientRegistrationRepository) {
   Assert.notNull(clientRegistrationRepository, "clientRegistrationRepository cannot be null");
   this.getBuilder().setSharedObject(ClientRegistrationRepository.class, clientRegistrationRepository);
   return this;
}

當你在HttpSecurity的配置中的其它地方須要用到ClientRegistrationRepository時,你能夠直接經過getSharedObject獲取,就像文章開頭同樣,而不用在去寫一些獲取方法了。

3. 總結

SharedObjectSpring Security提供的一個很是好用的功能,若是你在不一樣的地方須要對一個對象重複使用就能夠將它註冊爲SharedObject,甚至直接注入Spring IoC像開頭那樣獲取就能夠了。這個特性可以簡化配置,提升代碼的可讀性,也爲Spring SecurityDSL特性打下了基礎。好了今天的分享就到這裏,我是:碼農小胖哥,多多關注,獲取更多實用的編程乾貨。

關注公衆號:Felordcn 獲取更多資訊

我的博客:https://felord.cn

相關文章
相關標籤/搜索