SpringSecurity實戰:分佈式對象“可共享對象” 1. 前言 2. SharedObject SharedObject的註冊 SharedObject的獲取和使用

1. 前言

我們對 AuthenticationManager 的初始化的細節進行了分析,其中裏面有一段代碼引起了不少同學的注意:

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

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

2. SharedObject

Spring SecuritySharedObject 既不是對象也不是接口,而是某一類“可共享”的對象的統稱。

顧名思義, SharedObject 的意思是可共享的對象。它的作用是如果一些對象你希望在不同的作用域配置中共享它們就把這些對象變成 SharedObject ,有點分佈式對象的感覺。爲了更加便於你理解,下面是相關的體系結構:

AbstractConfiguredSecurityBuilder 或者 HttpSecurityBuilder 的實現類才具有操作SharedObject 的能力。一種是註冊 SharedObject ,另一種是獲取 SharedObject

SharedObject的註冊

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

我們熟知的 AuthenticationManagerBuilder 在這裏被共享。

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

public interface SecurityConfigurer<O, B extends SecurityBuilder<O>> {

   void init(B builder) throws Exception;

   void configure(B builder) throws Exception;
}

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

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 的根本原因。

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 獲取,就像文章開頭一樣,而不用在去寫一些獲取方法了。

來源:https://www.tuicool.com/articles/niqU7bz

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章