There is no relationship between objects created by the Spring Security framework and the container. However, many objects created by Spring Security framework can also be managed by the container.

ObjectPostProcessor Spring Security ObjectPostProcessor Spring Security ObjectPostProcessor

This is the 32nd article in the Spring Security series, and reading the previous articles will help you understand it better:

  1. Dig a big hole and Spring Security will do it!
  2. How to decrypt the password
  3. A step-by-step guide to customizing form logins in Spring Security
  4. Spring Security does front and back separation, so don’t do page jumps! All JSON interactions
  5. Authorization in Spring Security used to be so simple
  6. How does Spring Security store user data into the database?
  7. Spring Security+Spring Data Jpa, Security management is only easier!
  8. Spring Boot + Spring Security enables automatic login
  9. Spring Boot automatic login. How to control security risks?
  10. How is Spring Security better than Shiro in microservices projects?
  11. Two ways for SpringSecurity to customize authentication logic (advanced play)
  12. How can I quickly view information such as the IP address of the login user in Spring Security?
  13. Spring Security automatically kicks out the previous login user.
  14. How can I kick out a user who has logged in to Spring Boot + Vue?
  15. Spring Security comes with a firewall! You have no idea how secure your system is!
  16. What is a session fixed attack? How do I defend against session fixation attacks in Spring Boot?
  17. How does Spring Security handle session sharing in a clustered deployment?
  18. Songgo hand in hand to teach you in SpringBoot CSRF attack! So easy!
  19. Learn to learn thoroughly! Spring Security CSRF defense source code parsing
  20. Two poses for password encryption in Spring Boot!
  21. How to learn Spring Security? Why must we study systematically?
  22. Spring Security has two different resource release policies. Do not use them incorrectly.
  23. Spring Boot + CAS single sign-on
  24. Spring Boot is the third way to implement single sign-on!
  25. How do I Connect to the Database in Spring Boot+CAS SINGLE Sign-on?
  26. Spring Boot+CAS default login page is too ugly, how to do?
  27. How to carry Token in request header with Swagger
  28. Summary of three cross-domain scenarios in Spring Boot
  29. How to implement HTTP authentication in Spring Boot?
  30. Four types of permission control in Spring Security
  31. Spring Security multiple encryption solutions coexist, old and old system integration sharp tools!

If you have studied Songgo’s micro personnel project, you will find that the dynamic permission configuration in it has a line of code like this:

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .withObjectPostProcessor(new ObjectPostProcessor<FilterSecurityInterceptor>() {
                    @Override
                    public <O extends FilterSecurityInterceptor> O postProcess(O object) {
                        object.setAccessDecisionManager(customUrlDecisionManager);
                        object.setSecurityMetadataSource(customFilterInvocationSecurityMetadataSource);
                        returnobject; } }) .and() ... }}Copy the code

How do we understand the withObjectPostProcessor?

Today, Songo is here to solve the puzzle.

1. ObjectPostProcessor role

ObjectPostProcessor: ObjectPostProcessor: ObjectPostProcessor: ObjectPostProcessor: ObjectPostProcessor: ObjectPostProcessor: ObjectPostProcessor

package org.springframework.security.config.annotation;
public interface ObjectPostProcessor<T> {
	<O extends T> O postProcess(O object);
}
Copy the code

There is only one postProcess method in the interface.

ObjectPostProcessor: ObjectPostProcessor:

Two of the more important implementation classes, including AutowireBeanFactoryObjectPostProcessor worth saving, see AutowireBeanFactoryObjectPostProcessor definition:

final class AutowireBeanFactoryObjectPostProcessor
		implements ObjectPostProcessor<Object>, DisposableBean.SmartInitializingSingleton {
	AutowireBeanFactoryObjectPostProcessor(
			AutowireCapableBeanFactory autowireBeanFactory) {
		this.autowireBeanFactory = autowireBeanFactory;
	}
	@SuppressWarnings("unchecked")
	public <T> T postProcess(T object) {
		if (object == null) {
			return null;
		}
		T result = null;
		try {
			result = (T) this.autowireBeanFactory.initializeBean(object,
					object.toString());
		}
		catch(RuntimeException e) { Class<? > type = object.getClass();throw new RuntimeException(
					"Could not postProcess " + object + " of type " + type, e);
		}
		this.autowireBeanFactory.autowireBean(object);
		if (result instanceof DisposableBean) {
			this.disposableBeans.add((DisposableBean) result);
		}
		if (result instanceof SmartInitializingSingleton) {
			this.smartSingletons.add((SmartInitializingSingleton) result);
		}
		returnresult; }}Copy the code

AutowireBeanFactoryObjectPostProcessor source is easy to understand:

  1. First, when you build AutowireBeanFactoryObjectPostProcessor object into a AutowireCapableBeanFactory object, seen friends will know that Spring source, AutowireCapableBeanFactory can help us to an instance of manually register into the Spring container.
  2. In the postProcess method, there is the specific registration logic, which is very simple and I won’t go over it.

Thus, the main purpose of ObjectPostProcessor is to manually register the instance into the Spring container (and walk the instance through the Bean life cycle).

Normally, the beans in our project are injected into the Spring container through automatic scanning. However, in the Spring Security framework, there is a large amount of code that is not injected into the Spring container through automatic scanning, but is directly new. The intention is to simplify project configuration.

What if the code that comes out directly from new wants to be managed by the Spring container? That’s where ObjectPostProcessor comes in.

2. Framework examples

Here are a few examples of how ObjectPostProcessor works:

HttpSecurity initialization code (WebSecurityConfigurerAdapter# getHttp) :

protected final HttpSecurity getHttp(a) throws Exception {
	if(http ! =null) {
		returnhttp; }... . http =newHttpSecurity(objectPostProcessor, authenticationBuilder, sharedObjects); . . }Copy the code

WebSecurity initialization code (WebSecurityConfiguration# setFilterChainProxySecurityConfigurer) :

public void setFilterChainProxySecurityConfigurer(
		ObjectPostProcessor<Object> objectPostProcessor,
		@Value("#{@autowiredWebSecurityConfigurersIgnoreParents.getWebSecurityConfigurers()}") List<SecurityConfigurer<Filter, WebSecurity>> webSecurityConfigurers)
		throws Exception {
	webSecurity = objectPostProcessor
			.postProcess(newWebSecurity(objectPostProcessor)); . . }Copy the code

Manual assembly is everywhere in the source code of the Spring Security framework. Spring Security, all filters in the filter chain are configured by the corresponding xxxConfigure, and all the xxxConfigure is inherited from SecurityConfigurerAdapter, as follows:

In each of these xxxConfigure’s configure methods, their respective configured managers go around the Spring container, For example AbstractAuthenticationFilterConfigurer# configure method:

public void configure(B http) throws Exception {... . F filter = postProcess(authFilter); http.addFilter(filter); }Copy the code

The other xxxConfigurer#configure methods all have similar implementations, so you can check them out for yourself.

3. Why

Isn’t it a good idea to register beans directly with the Spring container through automatic scanning? Why do you have to do this?

In Spring Security, the framework itself makes heavy use of Java configuration and does not expose the individual properties of objects, which is intended to simplify configuration. One problem with this, however, is that we need to manually register the Bean into the Spring container, and ObjectPostProcessor is designed to solve this problem.

Once a Bean is registered with the Spring container, there is a way to enhance the functionality of a Bean, or to modify the properties of a Bean.

For example, the dynamic permission configuration code mentioned at the beginning:

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .withObjectPostProcessor(new ObjectPostProcessor<FilterSecurityInterceptor>() {
                    @Override
                    public <O extends FilterSecurityInterceptor> O postProcess(O object) {
                        object.setAccessDecisionManager(customUrlDecisionManager);
                        object.setSecurityMetadataSource(customFilterInvocationSecurityMetadataSource);
                        returnobject; } }) .and() ... }}Copy the code

Rights management itself is controlled by the FilterSecurityInterceptor, system default FilterSecurityInterceptor has created, and I didn’t also the way to modify its properties, then how to do? We can use withObjectPostProcessor methods, to revise relevant properties of the FilterSecurityInterceptor.

Above the configuration take effect one of the reasons is because FilterSecurityInterceptor, after creating the successful will retrace postProcess method again, here by rewriting postProcess method can modify attributes, We can see the configuration FilterSecurityInterceptor method (AbstractInterceptUrlConfigurer# configure) :

abstract class AbstractInterceptUrlConfigurer<C extends AbstractInterceptUrlConfigurer<C.H>, H extends HttpSecurityBuilder<H>>
		extends AbstractHttpConfigurer<C.H> {
	@Override
	public void configure(H http) throws Exception {
		FilterInvocationSecurityMetadataSource metadataSource = createMetadataSource(http);
		if (metadataSource == null) {
			return;
		}
		FilterSecurityInterceptor securityInterceptor = createFilterSecurityInterceptor(
				http, metadataSource, http.getSharedObject(AuthenticationManager.class));
		if(filterSecurityInterceptorOncePerRequest ! =null) { securityInterceptor .setObserveOncePerRequest(filterSecurityInterceptorOncePerRequest); } securityInterceptor = postProcess(securityInterceptor); http.addFilter(securityInterceptor); http.setSharedObject(FilterSecurityInterceptor.class, securityInterceptor); }}Copy the code

As you can see, once the securityInterceptor object is successfully created, it still goes through the postProcess method.

Now let me give you an example:

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/admin/**").hasRole("admin")... .and() .formLogin() .withObjectPostProcessor(new ObjectPostProcessor<UsernamePasswordAuthenticationFilter>() {
                    @Override
                    public <O extends UsernamePasswordAuthenticationFilter> O postProcess(O object) {
                        object.setUsernameParameter("name");
                        returnobject; }})... }}Copy the code

Here, I have configured UsernamePasswordAuthenticationFilter filter to carry out again, change the key user name (normally, modify the user name of the key don’t bother, ObjectPostProcessor (ObjectPostProcessor (username), ObjectPostProcessor (username), ObjectPostProcessor (username), ObjectPostProcessor (username), ObjectPostProcessor (username), ObjectPostProcessor (username), ObjectPostProcessor (username), ObjectPostProcessor (username)

4. Summary

If you want to modify the properties of an object in Spring Security, but don’t know where to start, try withObjectPostProcessor!

If you feel that there is a harvest, remember to click on the next songge oh ~