ObjectPostProcessor在WebSecurityConfig中的应用

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了,截图如下:


参考文献
Spring Security Config : 工具类 AutowireBeanFactoryObjectPostProcessor

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值