ObjectPostProcessor

ObjectPostProcessor

介绍

笔者在学习Spring Security,调试HeaderWriterFilter源码时,遇到了一个比较困惑的问题,HeaderWriterFilter在往请求头写入信息时,通过shouldWriteHeadersEagerly这个变量来控制,在调用过滤器之前写入还是调用doFilter()之后将信息写入到请求头当中,默认是过滤链执行后写入。笔者以为可以在ResourceServerConfig#configure()方法中,调用HttpSecurity.headers()进行配置,但并没有找到配置方法。笔者把Spring Security源码给下到了本地,在官方的测试用例中找到了答案,而且与这篇文章要介绍的 ObjectPostProcessor有关,代码如下:

@Override
protected void doFilterInternal(HttpServletRequest request,
        HttpServletResponse response, FilterChain filterChain)
        throws ServletException, IOException {

    if (this.shouldWriteHeadersEagerly) {
        doHeadersBefore(request, response, filterChain);
    } else {
        doHeadersAfter(request, response, filterChain);
    }
}
@EnableWebSecurity
public static class HeadersAtTheBeginningOfRequestConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //@ formatter:off
        http
            .headers()
                .addObjectPostProcessor(new ObjectPostProcessor<HeaderWriterFilter>() {
                    @Override
                    public HeaderWriterFilter postProcess(HeaderWriterFilter filter) {
                        filter.setShouldWriteHeadersEagerly(true);
                        return filter;
                    }
                });
        //@ formatter:on
    }
}

我们在学习Spring Security Filter源码的时候,会发现,相关的Filter都是以new的形式创建的,作为Java服务端开发,我们知道,new出来的对象是不受Spring Bean生命周期管控的。为了使这些Filter实例能够被Spring Bean容器管理,Spring Security定义了一个接口ObjectPostProcessor,AutowireBeanFactoryObjectPostProcessor实现了这个接口,通过postProcess方法手把Bean注入到spring容器进行管理。

代码分析

步骤1:AutowireBeanFactoryObjectPostProcessor

AutowireBeanFactoryObjectPostProcessor注册到Spring Bean容器,是通过@EnableWebSecurity注解一步步@Import实现的,代码如下:

// @EnableWebSecurity 注解代码片段,可以看到该注解隐含使用了@EnableGlobalMethodSecurity
@EnableGlobalAuthentication
@Configuration
public @interface EnableWebSecurity {

	/**
	 * Controls debugging support for Spring Security. Default is false.
	 * @return if true, enables debug support with Spring Security
	 */
	boolean debug() default false;
}
// @EnableGlobalAuthentication 注解代码片段,可以看到它导入了类 AuthenticationConfiguration
@Import(AuthenticationConfiguration.class)
@Configuration
public @interface EnableGlobalAuthentication {
}
@Configuration
@Import(ObjectPostProcessorConfiguration.class) // 导入了类 ObjectPostProcessorConfiguration
public class AuthenticationConfiguration {
	// 省略无关代码实现
}
@Configuration
public class ObjectPostProcessorConfiguration {

	// 这里的参数beanFactory会被自动注入成当前Spring bean容器
	@Bean
	public ObjectPostProcessor<Object> objectPostProcessor(
			AutowireCapableBeanFactory beanFactory) {
		return new AutowireBeanFactoryObjectPostProcessor(beanFactory);
	}
}

AutowireBeanFactoryObjectPostProcessor的代码分析笔者对代码的关键位置做了比较详细的注释,如下:

package org.springframework.security.config.annotation.configuration;

import java.util.ArrayList;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.springframework.beans.factory.Aware;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.security.config.annotation.ObjectPostProcessor;
import org.springframework.util.Assert;

final class AutowireBeanFactoryObjectPostProcessor
		implements ObjectPostProcessor<Object>, DisposableBean, SmartInitializingSingleton {
	private final Log logger = LogFactory.getLog(getClass());
	private final AutowireCapableBeanFactory autowireBeanFactory;
	private final List<DisposableBean> disposableBeans = new ArrayList<>();
	private final List<SmartInitializingSingleton> smartSingletons = new ArrayList<>();

	// 使用指定的 autowireBeanFactory 构造对象
	// autowireBeanFactory 通常是 Spring bean 容器
	public AutowireBeanFactoryObjectPostProcessor(
			AutowireCapableBeanFactory autowireBeanFactory) {
		Assert.notNull(autowireBeanFactory, "autowireBeanFactory cannot be null");
		this.autowireBeanFactory = autowireBeanFactory;
	}

	
	// 对某个刚刚创建的对象 object 执行这里所谓的 post-process 流程 :
	// 1. 使用指定的 autowireBeanFactory 对该对象 object 执行初始化过程;
	// 2. 使用指定的 autowireBeanFactory 对该对象 object 执行依赖注入过程;
	// 3. 如果该对象 object 是一个 DisposableBean , 则将它记录下来,在当前对象的destroy()
	//    被调用时,它们的 destroy() 方法也都会被调用;
	// 4. 如果该对象 object 是一个 SmartInitializingSingleton , 则将它记录下来,
	//    在当前对象的 afterSingletonsInstantiated () 被调用时,它们的 afterSingletonsInstantiated() 
	//    方法也都会被调用;
	@SuppressWarnings("unchecked")
	public <T> T postProcess(T object) {
		if (object == null) {
			return null;
		}
		T result = null;
		try {
			// 使用容器autowireBeanFactory标准初始化方法initializeBean()初始化对象 object
			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);
		}
		// 使用容器autowireBeanFactory标准依赖注入方法autowireBean()处理 object对象的依赖注入
		this.autowireBeanFactory.autowireBean(object);
		
		if (result instanceof DisposableBean) {
			// 记录一个 DisposableBean 对象
			this.disposableBeans.add((DisposableBean) result);
		}
		if (result instanceof SmartInitializingSingleton) {
			// 记录一个 SmartInitializingSingleton 对象
			this.smartSingletons.add((SmartInitializingSingleton) result);
		}
		return result;
	}
	
	// SmartInitializingSingleton 接口定义的生命周期方法,在被调用时也回调用被记录的实现了
	// SmartInitializingSingleton 接口的那些对象的方法 afterSingletonsInstantiated()
	@Override
	public void afterSingletonsInstantiated() {
		for (SmartInitializingSingleton singleton : smartSingletons) {
			singleton.afterSingletonsInstantiated();
		}
	}

	// DisposableBean 接口定义的生命周期方法,在被调用时也回调用被记录的实现了
	// DisposableBean 接口的那些对象的方法 destroy()
	public void destroy() throws Exception {
		for (DisposableBean disposable : this.disposableBeans) {
			try {
				disposable.destroy();
			}
			catch (Exception error) {
				this.logger.error(error);
			}
		}
	}

}

步骤2:ObjectPostProcessor

ObjectPostProcessor在Spring Security中广泛应用,我们这里就以HeaderWriterFilter为例, 像文章开始说的那样,笔者要修改shouldWriteHeadersEagerly的值,可以进行如下配置:

@Override
public void configure(HttpSecurity http) throws Exception {
    http.headers()
        .addObjectPostProcessor(new ObjectPostProcessor<HeaderWriterFilter>() {
            @Override
            public HeaderWriterFilter postProcess(HeaderWriterFilter filter) {
                filter.setShouldWriteHeadersEagerly(true);
                return filter;
            }
        });
}

在HeaderConfigurer这个类中,HeaderWriterFilter确实是new出来的,接着调用了postProcess()方法,进行后置处理。objectPostProcessor是一个复合的对象后置处理器,内部维护一个ObjectPostProcessor List, 调用postProcess()时,遍历ObjectPostProcessor List逐一处理传入的对象。这个List是在默认情况下,只包含一个ObjectPostProcessor,实现就是AutowireBeanFactoryObjectPostProcessor,但是我们自己配置了http.headers().addObjectPostProcessor(…),因此还有一个匿名ObjectPostProcessor,前者是将对象注入到Spring Bean容器,或者是显式调用容器中bean的方法改变对象的属性。CompositeObjectPostProcessor关键代码如下:

private CompositeObjectPostProcessor objectPostProcessor = new CompositeObjectPostProcessor();

private HeaderWriterFilter createHeaderWriterFilter() {
    List<HeaderWriter> writers = getHeaderWriters();
    if (writers.isEmpty()) {
        throw new IllegalStateException(
                "Headers security is enabled, but no headers will be added. Either add headers or disable headers security");
    }
    HeaderWriterFilter headersFilter = new HeaderWriterFilter(writers);
    headersFilter = postProcess(headersFilter);
    return headersFilter;
}

protected <T> T postProcess(T object) {
    return (T) this.objectPostProcessor.postProcess(object);
}
private List<ObjectPostProcessor<?>> postProcessors = new ArrayList<>();

@SuppressWarnings({ "rawtypes", "unchecked" })
public Object postProcess(Object object) {
    for (ObjectPostProcessor opp : postProcessors) {
        Class<?> oppClass = opp.getClass();
        Class<?> oppType = GenericTypeResolver.resolveTypeArgument(oppClass,
                ObjectPostProcessor.class);
        if (oppType == null || oppType.isAssignableFrom(object.getClass())) {
            object = opp.postProcess(object);
        }
    }
    return object;
}


项目启动后看,我们发起一个请求,发现shouldWriteHeadersEagerly已经为true了,截图如下:
ObjectPostProcessor_第1张图片

参考文献

  1. Spring Security Config : 工具类 AutowireBeanFactoryObjectPostProcessor

你可能感兴趣的:(spring,security)