Spring Security 4 源码阅读笔记 : WebSecurityConfiguration

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/andy_zhang2007/article/details/82313144
package org.springframework.security.config.annotation.web.configuration;

// 忽略 import 行


/**
* Spring Security 的配置类 : 
*  1. 使用一个 WebSecurity 对象创建执行 Spring Security 基于web的安全任务的 FilterChainProxy 对象。 
*  2. 也会暴露一些必要的 bean。
*  3. 如何定制 Spring security 的web 安全,也就是 WebSecurity 对象 ?
*     3.1 实现一个继承自 WebSecurityConfigurerAdapter 的配置类 , 
*     3.2 或者 提供一个配置类,实现了接口 WebSecurityConfigurer
*    该配置类的配置会在使用 @EnableWebSecurity 时应用到系统。
*
* Uses a WebSecurity to create the FilterChainProxy that performs the web based security 
* for Spring Security. It then exports the necessary beans. Customizations can be made to 
* WebSecurity by extending WebSecurityConfigurerAdapter and exposing it as a Configuration 
* or implementing WebSecurityConfigurer and exposing it as a Configuration. This configuration 
* is imported when using EnableWebSecurity.
*
* @see EnableWebSecurity
* @see WebSecurity
*
* @author Rob Winch
* @author Keesun Baik
* @since 3.2
*/
@Configuration
public class WebSecurityConfiguration implements ImportAware, BeanClassLoaderAware {
    private WebSecurity webSecurity;

    // 是否启用了调试模式,来自注解 @EnableWebSecurity 的属性 debug,缺省值 false
    private Boolean debugEnabled;

    private List<SecurityConfigurer<Filter, WebSecurity>> webSecurityConfigurers;

    private ClassLoader beanClassLoader;

    @Autowired(required = false)
    private ObjectPostProcessor<Object> objectObjectPostProcessor;

    @Bean
    public static DelegatingApplicationListener delegatingApplicationListener() {
        return new DelegatingApplicationListener();
    }

    // 定义一个bean,是表达式处理器,缺省为一个 DefaultWebSecurityExpressionHandler,
    //  仅在bean springSecurityFilterChain 被定义时才生效
    @Bean
    @DependsOn(AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME)
    public SecurityExpressionHandler<FilterInvocation> webSecurityExpressionHandler() {
        return webSecurity.getExpressionHandler();
    }

    /**
     * Creates the Spring Security Filter Chain 
     * 定义 Spring Security Filter Chain  , 名字为 springSecurityFilterChain
     * @return
     * @throws Exception
     */
    @Bean(name = AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME)
    public Filter springSecurityFilterChain() throws Exception {
        boolean hasConfigurers = webSecurityConfigurers != null
                && !webSecurityConfigurers.isEmpty();
        if (!hasConfigurers) {
            // 如果没有 webSecurityConfigurer, 则提供一个却省的
            WebSecurityConfigurerAdapter adapter = objectObjectPostProcessor
                    .postProcess(new WebSecurityConfigurerAdapter() {
                    });
            webSecurity.apply(adapter);
        }

        // 根据配置构建 Filter FilterChainProxy 并返回之
        return webSecurity.build();
    }

     // 定义一个bean,是web调用权限评估器,用于判断一个用户是否可以访问某个URL,
    // 对于 JSP tag 支持必要。 仅在bean springSecurityFilterChain 被定义时才生效。
    /**
     * Creates the WebInvocationPrivilegeEvaluator that is necessary for the JSP
     * tag support.
     * @return the WebInvocationPrivilegeEvaluator
     * @throws Exception
     */
    @Bean
    @DependsOn(AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME)
    public WebInvocationPrivilegeEvaluator privilegeEvaluator() throws Exception {
        return webSecurity.getPrivilegeEvaluator();
    }

    /**
     * Sets the <SecurityConfigurer<FilterChainProxy, WebSecurityBuilder>
     * instances used to create the web configuration.
     *
     * @param objectPostProcessor the ObjectPostProcessor used to create a
     * WebSecurity instance
     * @param webSecurityConfigurers the
     * <SecurityConfigurer<FilterChainProxy, WebSecurityBuilder> instances used to
     * create the web configuration
     * @throws Exception
     */
    @Autowired(required = false)
    public void setFilterChainProxySecurityConfigurer(
            ObjectPostProcessor<Object> objectPostProcessor,
            @Value("#{@autowiredWebSecurityConfigurersIgnoreParents.getWebSecurityConfigurers()}") List<SecurityConfigurer<Filter, WebSecurity>> webSecurityConfigurers)
            throws Exception {
        webSecurity = objectPostProcessor
                .postProcess(new WebSecurity(objectPostProcessor));
        if (debugEnabled != null) {
            webSecurity.debug(debugEnabled);
        }

        Collections.sort(webSecurityConfigurers, AnnotationAwareOrderComparator.INSTANCE);

        Integer previousOrder = null;
        Object previousConfig = null;
        for (SecurityConfigurer<Filter, WebSecurity> config : webSecurityConfigurers) {
            Integer order = AnnotationAwareOrderComparator.lookupOrder(config);
            if (previousOrder != null && previousOrder.equals(order)) {
                throw new IllegalStateException(
                        "@Order on WebSecurityConfigurers must be unique. Order of "
                                + order + " was already used on " + previousConfig + ", so it cannot be used on "
                                + config + " too.");
            }
            previousOrder = order;
            previousConfig = config;
        }
        for (SecurityConfigurer<Filter, WebSecurity> webSecurityConfigurer : webSecurityConfigurers) {
            webSecurity.apply(webSecurityConfigurer);
        }
        this.webSecurityConfigurers = webSecurityConfigurers;
    }

    @Bean
    public AutowiredWebSecurityConfigurersIgnoreParents autowiredWebSecurityConfigurersIgnoreParents(
            ConfigurableListableBeanFactory beanFactory) {
        return new AutowiredWebSecurityConfigurersIgnoreParents(beanFactory);
    }

    /**
     * A custom verision of the Spring provided AnnotationAwareOrderComparator that uses
     * AnnotationUtils#findAnnotation(Class, Class) to look on super class
     * instances for the Order annotation.
     *
     * @author Rob Winch
     * @since 3.2
     */
    private static class AnnotationAwareOrderComparator extends OrderComparator {
        private static final AnnotationAwareOrderComparator INSTANCE = new AnnotationAwareOrderComparator();

        @Override
        protected int getOrder(Object obj) {
            return lookupOrder(obj);
        }

        private static int lookupOrder(Object obj) {
            if (obj instanceof Ordered) {
                return ((Ordered) obj).getOrder();
            }
            if (obj != null) {
                Class<?> clazz = (obj instanceof Class ? (Class<?>) obj : obj.getClass());
                Order order = AnnotationUtils.findAnnotation(clazz, Order.class);
                if (order != null) {
                    return order.value();
                }
            }
            return Ordered.LOWEST_PRECEDENCE;
        }
    }

    /*
     * 获取导入该配置bean的配置bean上的注解元数据并设置到该配置bean
     *  这里主要是为了获取注解 @EnableWebSecurity 的属性 debugEnabled
     *
     * @see org.springframework.context.annotation.ImportAware#setImportMetadata(org.
     * springframework.core.type.AnnotationMetadata)
     */
    public void setImportMetadata(AnnotationMetadata importMetadata) {
        Map<String, Object> enableWebSecurityAttrMap = importMetadata
                .getAnnotationAttributes(EnableWebSecurity.class.getName());
        AnnotationAttributes enableWebSecurityAttrs = AnnotationAttributes
                .fromMap(enableWebSecurityAttrMap);
        debugEnabled = enableWebSecurityAttrs.getBoolean("debug");
        if (webSecurity != null) {
            webSecurity.debug(debugEnabled);
        }
    }

    /*
     *
     *
     * @see
     * org.springframework.beans.factory.BeanClassLoaderAware#setBeanClassLoader(java.
     * lang.ClassLoader)
     */
    public void setBeanClassLoader(ClassLoader classLoader) {
        this.beanClassLoader = classLoader;
    }
}

猜你喜欢

转载自blog.csdn.net/andy_zhang2007/article/details/82313144
今日推荐