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構建

 未完待續……

相關文章
相關標籤/搜索