SpringSecurity源码解读

1.前言

官方解释以下html

Spring Security is a powerful and highly customizable authentication and access-control framework. 
It is the de-facto standard for securing Spring-based applications. Spring Security is a framework that focuses on providing both authentication and authorization to Java applications.
Like all Spring projects, the real power of Spring Security is found in how easily it can be extended to meet custom requirements.

https://spring.io/projects/spring-securityjava

 

SpringSecurity项目继承WebSecurityConfigurerAdapter完成拦截鉴权逻辑,以下web

@EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers("/", "/home").permitAll() .anyRequest().authenticated() .and() .formLogin() .loginPage("/login") .permitAll() .and() .logout() .permitAll(); } @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder()) .withUser("admin").password(new BCryptPasswordEncoder().encode("admin")).roles("USER"); } }

 

Spring鉴权认证思路就是利用J2EE的Filter,上面的WebSecurityConfigurerAdapter大量的configure操做,最终目的就是为了建立一个FilterChainProxy(bean's name: springSecurityFilterChain)实例。spring

 为了分析SpringSecurity框架原理,本文带你们追溯源码,分析springSecurityFilterChain的定义初始化过程。api

 

1.启动入口

J2EE定义了javax.servlet.ServletContainerInitializer接口,就是为了替换之前普通的web项目的web.xml功能,使用者能够使用ServletContainerInitializer和SPI完成servlet/filter/listener定义,能够看官方文档定义oracle

Spring Framework定义了SpringServletContainerInitializer类和WebApplicationInitializer接口,SpringBoot也定义了函数接口org.springframework.boot.web.servlet.ServletContextInitializer,二者功能相似,都是替换web.xml定义使用的,可是SpringBoot新定义类能够解决war包的冲突问题,场景如:app

假如项目pay-web打包为pay-web.war,pay-web.war同时包含了SpringBoot和SpringFramework相关类,但pay-web.war只用到SpringFramework的特性,跑在Tomcat容器。框架

容器在加载SpringFramework的SpringServletContainerInitializer,会默认寻找类路径全部的WebApplicationInitializer实现类,这个SpringBoot的starter复用SpringFramework接口WebApplicationInitializer,实现了相关的逻辑,那么会出现问题。ide

因此SpringBoot单独定义了一个ServletContextInitializer类。详细能够看官方文档函数

 

SpringBoot使用的AnnotationConfigServletWebServerApplicationContext的容器,它父类ServletWebServerApplicationContext的onRefresh方法提供了构建webServer细节,即从Spring的BeanFactory获取全部的ServletContextInitializer类。

SpringSecurity使用SecurityFilterAutoConfiguration构建了DelegatingFilterProxyRegistrationBean实例。

 而咱们的DelegatingFilterProxyRegistrationBean恰好就是一个ServletContextInitializer的实现类。

DelegatingFilterProxyRegistrationBean执行onStartup()方法逻辑,会注册Filter到ServletContext中,以下

上图所示,留意上面的$1,因此Filter的实现类是一个DelegatingFilterProxy匿名继承类

 

2.小结

  a).SpringBoot初始化SpringSecurity的@Configuration类,构建一个匿名类DelegatingFilterProxyRegistrationBean$1实例,这个匿名类继承DelegatingFilterProxy

  b).匿名类DelegatingFilterProxyRegistrationBean$1实例(继承DelegatingFilterProxy)包裹了springSecurityFilterChain实例。

  c).匿名类DelegatingFilterProxyRegistrationBean$1实例注册Filter映射url(默认为/*)到ServletContext中。

 

3.springSecurityFilterChain加载

SpringSecurity经过类WebSecurityConfiguration定义了一个bean名为springSecurityFilterChain的实例,以下。

 上图显示springSecurityFilterChain实质上是经过WebSecurity调用build方法完成构建的,下面是WebSecurity的performBuild详情

因此,咱们的springSecurityFilterChain实例实质上是FilterChainProxy类型,FilterChainProxy有两类组成:

  a).ignoredRequests生成的DefaultSecurityFilterChain实例

  b).模板类SecurityBuilder(实质上就是HttpSecurity类)调用buid方法生成的实例。

上图所示,HttpSecurity就是上面内容"前言"例子的configure参数HttpSecurity,因此咱们经过WebSecurityConfigurerAdapter调用configure方法配置HttpSecurity结果会在这里用上。

4.HttpSecurity构建

 未完待续……

相关文章
相关标签/搜索