1. Preface

We previously analyzed the details of the initialization of AuthenticationManager, and there was a piece of code in it that caught the attention of many people.

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

How does the above get the Spring application context object ApplicationContext directly from the HttpSecurity object? And what is the concept of SharedObject? Let’s figure this out today.

2. SharedObject

In Spring Security SharedObject is neither an object nor an interface, but a generic term for a class of “sharable” objects.

As the name implies, SharedObject means a shareable object. What it does is if there are objects that you want to share in different scope configurations, you turn those objects into SharedObject, which is a bit of a distributed object. To make it easier for you to understand, here is the architecture.

SharedObject

An implementation class of AbstractConfiguredSecurityBuilder or HttpSecurityBuilder has the ability to manipulate SharedObject. One is to register SharedObject and the other is to get SharedObject.

Registration of SharedObject

A SharedObject is stored in a HashMap<Class<? >,Object>, see the HttpSecurity source code for details. Its registration is divided into two parts, the first is HttpSecurity initialization when assembled into. Let’s take a look.

SharedObject

The familiar AuthenticationManagerBuilder is shared here.

There is also a part that is registered during the initialization of all HttpSecurityBuilder objects. It is initialized and configured by the SecurityConfigurer.

1
2
3
4
5
6
public interface SecurityConfigurer<O, B extends SecurityBuilder<O>> {

   void init(B builder) throws Exception;

   void configure(B builder) throws Exception;
}

The above two methods are used to initialize and configure HttpSecurityBuilder respectively. For example, the familiar WebSecurityConfigurerAdapter is used to configure HttpSecurity, and we can find the relevant code in its init method.

1
2
3
4
5
6
7
8
9
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;
}

This is the fundamental reason why I could get ApplicationContext at the beginning of the article.

Getting and using SharedObject

What classes can we get that are marked as SharedObject? There are many implementations of SecurityConfigurer that are used to configure specific authentication-related functions. For example, OAuth2ClientConfigurer is used to configure the OAuth2 client, and it sets some common objects as SharedObject.

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

When you need to use ClientRegistrationRepository elsewhere in the HttpSecurity configuration, you can get it directly through getSharedObject, just like at the beginning of the article, without having to write some methods to get it.

3. Summary

SharedObject is a very useful feature provided by Spring Security, if you need to reuse an object in different places you can register it as a SharedObject or even inject it directly into Spring IoC and get it like at the beginning. This feature simplifies configuration, improves code readability, and provides the foundation for Spring Security’s DSL feature.

Reference https://felord.cn/spring-security-shared-object.html