【spring Security】 SpringBoot集成

Spring Security

1、POM依賴

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
    <version>2.2.0 RELEASE<version>
</dependency>

2、 默認配置

添加依賴後,便可實現Spring Security的默認配置。
spring-boot-autoconfigurer項目下的WebSecurityEnablerConfiguration 自動加載Spring Security 默認配置[WebSecurityConfigurerAdapter]web

Spring Security 默認配置主要以下:spring

  1. URL攔截(未登陸,重定向登陸頁面)
  2. 登陸頁面 [GET]/login
  3. 登陸接口 [POST]/login [from-data]username=xxx&password=xxx&_csrf=xxx
  4. 登出頁面 [GET]/logout
  5. 登出接口 [POST]/logout
  6. 默認帳號 username=user&password=xxx[在項目啓動時會輸出初始密碼 Using generated security password:xxx]

3、過濾器鏈

若是你是第一次使用Spring Security,必定會以爲很cool!Spring Security是如何作到的。api

Spring Security主要基於過濾器(責任鏈模式)和AOP實現。session

過濾器的結構大體是這麼個意思
image.pngapp

那麼FilterChainProxy是如何構建出來的?異步

Spring Security提供了兩個接口ide

  1. SecurityBuilder<O> 泛型O表明構造器構建的對象類型
    1.1 build() 構建並返回O對象
  2. SecurityConfigurer<O,B extends SecurityBuilder<O>> 泛型B表明可配置的構造器類型,泛型O表明構造器構建的對象類型
    2.1 init(B builder) 初始化SecurityBuilder
    2.2 configure(B builder) 配置SecurityBuilder

Spring Security基於構造器模式,經過SecurityBuilder構造器構建對象,而SecurityConfigurer則負責對構造器進行初始化和配置。spring-boot

FilterChainProxy經過WebSecurity構造器構建。post

默認的WebSecurityWebSecurityConfiguration.setFilterChainProxySecurityConfigurer()完成初始化,
並從Spring容器中獲取SecurityConfigurers<Filter, WebSecurity>列表實現對構造器的初始化和配置。ui

package org.springframework.security.config.annotation.web.configuration;

@Configuration(proxyBeanMethods = false)
public class WebSecurityConfiguration implements ImportAware, BeanClassLoaderAware {
    private WebSecurity webSecurity;
    private List<SecurityConfigurer<Filter, WebSecurity>> webSecurityConfigurers;
    ...
    // 經過WebSecurity完成FilterChainProxy構建並註冊到Spring容器
    @Bean(name = AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME)
    public Filter springSecurityFilterChain() throws Exception {
        ...
        return webSecurity.build();
    }
    ...
    // 1 從spring容器中獲取SecurityConfigurers<Filter, WebSecurity>配置列表
    // 2 建立WebSecurity
    // 3 將配置列表添加到WebSecurity
    @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));
        ...
        for (SecurityConfigurer<Filter, WebSecurity> webSecurityConfigurer : webSecurityConfigurers) {
            webSecurity.apply(webSecurityConfigurer);
        }
        ...
    }
    ...
}

SecurityFilterChain經過HttpSecurity構造器構建。
默認的HttpSecurity在WebSecurityConfigurerAdapter.init()完成初始化,該方法是WebSecurity在構建FilterChainProxy的過程當中觸發,並最終完成SecurityFilterChain構建添加到FilterChainProxy中。

package org.springframework.security.config.annotation.web.configuration;

@Order(100)
public abstract class WebSecurityConfigurerAdapter implements
        WebSecurityConfigurer<WebSecurity> {
    ...
    private HttpSecurity http;
    private boolean disableDefaults;
    ...
    // 初始化WebSecurity,在WebSecurity構建FilterChainProxy的過程當中觸發
    public void init(final WebSecurity web) throws Exception {
        final HttpSecurity http = getHttp();
        web.addSecurityFilterChainBuilder(http)...;
    }
    ...
    // 配置WebSecurity
    public void configure(WebSecurity web) {
    }
    ...       
    // 建立並返回HttpSecurity
    @SuppressWarnings({ "rawtypes", "unchecked" })
    protected final HttpSecurity getHttp() throws Exception {
        if (http != null) {
            return http;
        }
        ...
        http = new HttpSecurity(objectPostProcessor, authenticationBuilder,
                sharedObjects);
        if (!disableDefaults) {
            http
                .csrf().and()
                .addFilter(new WebAsyncManagerIntegrationFilter())
                .exceptionHandling().and()
                .headers().and()
                .sessionManagement().and()
                .securityContext().and()
                .requestCache().and()
                .anonymous().and()
                .servletApi().and()
                .apply(new DefaultLoginPageConfigurer<>()).and()
                .logout();
            ClassLoader classLoader = this.context.getClassLoader();
            List<AbstractHttpConfigurer> defaultHttpConfigurers =
                    SpringFactoriesLoader.loadFactories(AbstractHttpConfigurer.class, classLoader);

            for (AbstractHttpConfigurer configurer : defaultHttpConfigurers) {
                http.apply(configurer);
            }
        }
        configure(http);
        return http;
    }
    ...
    // 配置HttpSecurity
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .anyRequest().authenticated()
                .and()
            .formLogin().and()
            .httpBasic();
    }
    ...
}

下面則列出了一些"苦力"過濾器(默認過濾器列表)
固然,如下過濾器一般有對應的securityConfigurer完成構建。
構建邏輯在HttpSecurity的構建過程當中,觸發在其對應的SecurityConfigurer.configure(H http)中建立過濾器實例並添加到HttpSecurity中,最終添加到FilterChainProxy實例中。

1. WebAsyncManagerIntegrationFilter 支持集成Spring的異步調用
2. SecurityContextPersistenceFilter 從Session中獲取SecurityContext,沒有則新建,最終放入SecurityContextHolder中。
3. HeaderWriterFilter 往響應對象response中寫入Header屬性(Like X-Frame-Options, X-XSS-Protection and X- Content-Type-Options)
4. CsrfFilter csrf校驗
5. LogoutFilter 默認攔截[POST]/logout 處理登出邏輯
6. UsernamePasswordAuthenticationFilter 默認攔截[POST]/login 處理登陸認證邏輯
    6.1 第一步 封裝Authentication(從request中獲取認證信息封裝爲UsernamePasswordAuthenticationToken)
    6.2 第二步 獲取AuthenticationManager實例[ProviderManager]
    6.3 第三步 ProviderManager基於委託者模式經過AuthenticationProvider列表完成認證
    6.4 第四步 認證經過後,將Authentication放入SecurityContextHolder的SecurityContext中。
7. DefaultLoginPageGeneratingFilter 默認攔截[GET]/login 生成登陸頁面
8. DefaultLogoutPageGeneratingFilter 默認攔截[POST]/login 生成登出頁面 
9. BasicAuthenticationFilter 認證Basic [Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==]
10. RequestCacheAwareFilter 用於用戶登陸成功後,從新恢復由於登陸被打斷的請求
11. SecurityContextHolderAwareRequestFilter 包裝request實現servlet api的一些接口方法isUserInRole、getRemoteUser
12. AnonymousAuthenticationFilter 匿名用戶認證、信息填充
13. SessionManagementFilter Session管理
14. ExceptionTranslationFilter 異常處理
15. FilterSecurityInterceptor 權限校驗、未登陸攔截、無權限攔截
...

4、自定義配置

相關文章
相關標籤/搜索