SpringBootspring security服务治理

Spring Security原理篇(一) 启动原理

2018-09-14  本文已影响875人  怪诞140819

1.概述

2.启动

2.1 简单的开始

从文档中可知,spring引入我们的项目只需要分为两步

 <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
 </dependency>
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth
            .inMemoryAuthentication()
                .withUser("user").password("password").roles("USER");
    }
}

2.2 简单后面的繁琐

我们洁简的应用spring security到我们的项目,然后却开启了非常强大的功能,上面的例子,在内存中配置了一个用户名为user,密码为password,并且拥有USER角色的用户。我们还是要探究一下,spring security到底为我们做了一些什么样的工作。
我们的入手点只有两个,@EnableWebSecurity注解和WebSecurityConfigurerAdapter这个适配器类。

2.2.1 @EnableWebSecurity 注解

注解源代码

@Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME)
@Target(value = { java.lang.annotation.ElementType.TYPE })
@Documented
@Import({ WebSecurityConfiguration.class,
        SpringWebMvcImportSelector.class,
        OAuth2ImportSelector.class })
@EnableGlobalAuthentication
@Configuration
public @interface EnableWebSecurity {
    boolean debug() default false;

此处还是有必要简单翻译一下官方对于类的注释,以便于更加清楚的理解注解的作用
注释中提到两个很重要的点,以及一个配置示例,

由此可知@EnableWebSecurity使我们拥有spring security的能力。WebSecurityConfigurer 使我们能根据业务扩展我们的应用,而WebSecurityConfigurerAdapterWebSecurityConfigurer 的一个适配器,必然也是做了很多默认的工作。后面我们会一一说到。

从以上可以稍微总结一下我们下一步需要探究的问题,

2.2.2 spring security创建流程

spring security加载流程

WebSecurityConfiguration中的 setFilterChainProxySecurityConfigurer()方法

@Autowired(required = false)
    public void setFilterChainProxySecurityConfigurer(
            ObjectPostProcessor<Object> objectPostProcessor,
            //T1 使用@Value获取到配置信息
            @Value("#{@autowiredWebSecurityConfigurersIgnoreParents.getWebSecurityConfigurers()}") List<SecurityConfigurer<Filter, WebSecurity>> webSecurityConfigurers)
            throws Exception {
   
         //T2 创建一个webSecurity 对象
        webSecurity = objectPostProcessor
                .postProcess(new WebSecurity(objectPostProcessor));
        if (debugEnabled != null) {
            webSecurity.debug(debugEnabled);
        }
                
        //T3对configures进行排序
        Collections.sort(webSecurityConfigurers, AnnotationAwareOrderComparator.INSTANCE);
      
         //T4对Order进行比较是否有相同的,由于前面进行了排序,只要比较前后有相同的就可以
        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) {
            //T5将配置信息配置到webSecurity中
            webSecurity.apply(webSecurityConfigurer);
        }
        this.webSecurityConfigurers = webSecurityConfigurers;
    }
@Value("#{@autowiredWebSecurityConfigurersIgnoreParents.getWebSecurityConfigurers()}"

可以看一下autowiredWebSecurityConfigurersIgnoreParents.getWebSecurityConfigurers()的源代码

public List<SecurityConfigurer<Filter, WebSecurity>> getWebSecurityConfigurers() {
        List<SecurityConfigurer<Filter, WebSecurity>> webSecurityConfigurers = new ArrayList<SecurityConfigurer<Filter, WebSecurity>>();
        Map<String, WebSecurityConfigurer> beansOfType = beanFactory
                .getBeansOfType(WebSecurityConfigurer.class);
        for (Entry<String, WebSecurityConfigurer> entry : beansOfType.entrySet()) {
            webSecurityConfigurers.add(entry.getValue());
        }
        return webSecurityConfigurers;
    }

其实我们根据debug获取到的来看,这个beansOfType 就是我们定义的继承自WebSecurityConfigurerAdapter的类,通过查看父类的定义,我们知道调用build()方法最后返回的必须是一个Filter对象,可以自行参考顶级父类(或接口)WebSecurityConfigurerSecurityBuilder

WebSecurityConfiguration中的 springSecurityFilterChain()方法

@Bean(name = AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME)
    public Filter springSecurityFilterChain() throws Exception {
        boolean hasConfigurers = webSecurityConfigurers != null
                && !webSecurityConfigurers.isEmpty();
        //这里的意思是我们是否有自定义配置其实就是是否有注入WebSecurityConfigurer的子类,没有的话,我默认的创建一个默认的,但是默认的我们自己不可修改
        if (!hasConfigurers) {
            WebSecurityConfigurerAdapter adapter = objectObjectPostProcessor
                    .postProcess(new WebSecurityConfigurerAdapter() {
                    });
           //请参考上面的代码
            webSecurity.apply(adapter);
        }
       //现在为止webSecurity对象的信息已经填充完毕,我们可以构建一个Filter
        return webSecurity.build();
    }

2.2.3 WebSecurityConfigurerAdapter为我们做了什么

上一篇 下一篇

猜你喜欢

热点阅读