1. 程式人生 > >SpringSecurity 初始化流程原始碼

SpringSecurity 初始化流程原始碼

SpringSecurity 初始化流程原始碼

本篇主要講解 SpringSecurity初始化流程的原始碼部分,包括核心的 springSecurityFilterChain 是如何建立的,以及在介紹哪裡可以擴充套件個性化的配置,SpringSecurity原始碼其實是蠻難得 各種Builder Configure 看得真的頭疼!

 1.簡單介紹

 SpringSecurity 的核心功能主要包括:

 認證 (你是誰)
 授權 (你能幹什麼)
 攻擊防護 (防止偽造身份)

 其核心就是一組過濾器鏈,專案啟動後將會自動配置,本篇也會涉及過濾器鏈是如何自動初始化的。

 SecurityContextPersistenceFilter 是最前面的一個filter
 請求到它時候會去檢查 根據sessionId找到session 判斷session 中是否存在 SecurityContext 在 則將 SecurityContext 存入當前的執行緒中去
 響應的時候,看當前執行緒是否有SecurityContext ,如果有 放入到session中去 這樣不同的請求都能拿到相同的 使用者認證資訊。

 UsernamePasswordAuthenticationFilter 該過濾器是處理表單登入的,通過表單登入提交的認證都會經過它處理

 SocialAuthenticationFilter 比如這個就是社交登入使用的Filter
 詳細可以看我另外一篇 SpringSocial 實現第三方QQ登入SpringSocial 實現第三方QQ登入

 綠色的過濾器都是可配置的,其他顏色的都不行!

 2.SecurityAutoConfiguration

 如果是SpringBoot專案只要你依賴了SpringSecurity相關依賴依然會有自動配置類
SecurityAutoConfiguration 生效 它會匯入 WebSecurityEnableConfiguration

 @EnableWebSecurity將會是我們本篇的主要切入點

 3.@EnableWebSecurity註解介紹

 該註解 它是初始化Spring Security的入口 .

 開啟@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 {

/**
 * Controls debugging support for Spring Security. Default is false.
 * @return if true, enables debug support with Spring Security
 */
boolean debug() default false;
}

 該註解類通過@Configuration和@Import配合使用引入了一個配置類(WebSecurityConfiguration)和兩個ImportSelector(SpringWebMvcImportSelector,OAuth2ImportSelector),我們重點關注下WebSecurityConfiguration,它是Spring Security的核心

 4.springSecurityFilterChain初始化流程及原始碼

 開啟WebSecurityConfiguration 它是一個配置類,主要看 springSecurityFilterChain()方法,它就是初始化
springSecurityFilterChain的核心方法

/**
 * Creates the Spring Security Filter Chain
 * @return the {@link Filter} that represents the security filter chain
 * @throws Exception
 */
@Bean(name = AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME)
public Filter springSecurityFilterChain() throws Exception {
    boolean hasConfigurers = webSecurityConfigurers != null
            && !webSecurityConfigurers.isEmpty();
    if (!hasConfigurers) {
        WebSecurityConfigurerAdapter adapter = objectObjectPostProcessor
                .postProcess(new WebSecurityConfigurerAdapter() {
                });
        webSecurity.apply(adapter);
    }
    return webSecurity.build();
}

 @Bean註解name屬性值AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME就是XML中定義的springSecurityFilterChain

 從原始碼中知道過濾器通過最後的 webSecurity.build()建立,webSecurity的型別為:WebSecurity,它在 setFilterChainProxySecurityConfigurer方法中優先被建立了:

@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);
    }

    webSecurityConfigurers.sort(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;
}

 從程式碼中可以看到,它是直接被new出來的:

webSecurity = objectPostProcessor
            .postProcess(new WebSecurity(objectPostProcessor));

 setFilterChainProxySecurityConfigurer 該方法的webSecurityConfigurers 引數是通過@Value注入的

@Value("#{@autowiredWebSecurityConfigurersIgnoreParents.getWebSecurityConfigurers()}")

 AutowiredWebSecurityConfigurersIgnoreParents的 getWebSecurityConfigurers()
 如下,就是獲取所有的 WebSecurityConfigurer的型別的配置類
 而通常 我們通過繼承 WebSecurityConfigurerAdapter 來自定義WebSecurityConfigurer

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

 再回到setFilterChainProxySecurityConfigurer方法 下面有一段這樣的程式碼 ,對於上面獲取的所有的WebSecurityConfigurer型別 迴圈執行 webSecurity的apply方法

for (SecurityConfigurer<Filter, WebSecurity> webSecurityConfigurer : webSecurityConfigurers) {
        webSecurity.apply(webSecurityConfigurer);
    }

 webSecurity整合AbstractConfiguredSecurityBuilder 它提供apply方法 再其內部呼叫add方法

public <C extends SecurityConfigurer<O, B>> C apply(C configurer) throws Exception {
    add(configurer);
    return configurer;
}

 add(configurer),主要就是將其傳入的WebSecurityConfigurer存入到 LinkedHashMap configures中,
主要程式碼 this.configurers.put(clazz, configs);

private <C extends SecurityConfigurer<O, B>> void add(C configurer) {
    Assert.notNull(configurer, "configurer cannot be null");

    Class<? extends SecurityConfigurer<O, B>> clazz = (Class<? extends SecurityConfigurer<O, B>>) configurer
            .getClass();
    synchronized (configurers) {
        if (buildState.isConfigured()) {
            throw new IllegalStateException("Cannot apply " + configurer
                    + " to already built object");
        }
        List<SecurityConfigurer<O, B>> configs = allowConfigurersOfSameType ? this.configurers
                .get(clazz) : null;
        if (configs == null) {
            configs = new ArrayList<>(1);
        }
        configs.add(configurer);
        this.configurers.put(clazz, configs);
        if (buildState.isInitializing()) {
            this.configurersAddedInInitializing.add(configurer);
        }
    }
}

 當所有的 WebSecurityConfigurer 型別的配置 全部應用到 WebSecurity中去後 setFilterChainProxySecurityConfigurer方法也就結束了


 回到建立過濾器鏈的方法 springSecurityFilterChain()

 它會判斷我們剛剛的webSecurityConfigurers是否存在,不存在就新建一個,然後執行 webSecurity.build() 重要!

@Bean(name = AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME)
public Filter springSecurityFilterChain() throws Exception {
    boolean hasConfigurers = webSecurityConfigurers != null
            && !webSecurityConfigurers.isEmpty();
    if (!hasConfigurers) {
        WebSecurityConfigurerAdapter adapter = objectObjectPostProcessor
                .postProcess(new WebSecurityConfigurerAdapter() {
                });
        webSecurity.apply(adapter);
    }
    return webSecurity.build();
}

 最終內部會有下面這段程式碼, 主要關注 init() configure() 和 performBuild() 這三個方法

@Override
protected final O doBuild() throws Exception {
    synchronized (configurers) {
        buildState = BuildState.INITIALIZING;

        beforeInit();
        init();

        buildState = BuildState.CONFIGURING;

        beforeConfigure();
        configure();

        buildState = BuildState.BUILDING;

        O result = performBuild();

        buildState = BuildState.BUILT;

        return result;
    }
}

 init() 內部迴圈遍歷 所有的 WebSecurityConfigurer ,它會執行到 WebSecurityConfigurerAdapter的

private void init() throws Exception {
    Collection<SecurityConfigurer<O, B>> configurers = getConfigurers();

    for (SecurityConfigurer<O, B> configurer : configurers) {
        configurer.init((B) this);
    }

    for (SecurityConfigurer<O, B> configurer : configurersAddedInInitializing) {
        configurer.init((B) this);
    }
}

 configurer.init((B) this)

 它只要完成兩件重要的事情:

 初始化HttpSecurity物件(注意它和WebSecurity不一樣 );
 設定HttpSecurity物件新增至WebSecurity的securityFilterChainBuilders列表中;

public void init(final WebSecurity web) throws Exception {
    final HttpSecurity http = getHttp();
    web.addSecurityFilterChainBuilder(http).postBuildAction(() -> {
        FilterSecurityInterceptor securityInterceptor = http
                .getSharedObject(FilterSecurityInterceptor.class);
        web.securityInterceptor(securityInterceptor);
    });
}

初始化HttpSecurity物件在getHttp()方法中實現:

protected final HttpSecurity getHttp() throws Exception {
    if (http != null) {
        return http;
    }

    DefaultAuthenticationEventPublisher eventPublisher = objectPostProcessor
            .postProcess(new DefaultAuthenticationEventPublisher());
    localConfigureAuthenticationBldr.authenticationEventPublisher(eventPublisher);

    AuthenticationManager authenticationManager = authenticationManager();
    authenticationBuilder.parentAuthenticationManager(authenticationManager);
    authenticationBuilder.authenticationEventPublisher(eventPublisher);
    Map<Class<?>, Object> sharedObjects = createSharedObjects();

    http = new HttpSecurity(objectPostProcessor, authenticationBuilder,
            sharedObjects);
    if (!disableDefaults) {
        // @formatter:off
        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();
        // @formatter:on
        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是直接被new出來的,在建立HttpSecurity之前,首先初始化了AuthenticationManagerBuilder物件,這裡有段程式碼很重要就是: AuthenticationManager authenticationManager = authenticationManager();,它建立AuthenticationManager例項,開啟authenticationManager()方法:

 預設實現是在 WebSecurityConfigurerAdapter 中

protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    this.disableLocalConfigureAuthenticationBldr = true;
}

 1、個性化配置入口之configure(AuthenticationManagerBuilder auth)

 我們可以通過繼承WebSecurityConfigurerAdapter並重寫該方法來個性化配置AuthenticationManagerBuilder。

 如下是自己繼承WebSecurityConfigurerAdapter 重寫 configure(AuthenticationManagerBuilder auth),實現個性化的第一個配置入口

/**
* @author johnny
* @create 2020-01-18 下午6:40
**/
@Configuration
@Slf4j
public class MyWebSecurityConfig extends WebSecurityConfigurerAdapter {


@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    super.configure(auth);
    log.info("【測試 定製化入口  configure(AuthenticationManagerBuilder auth)  的執行 】");
}
}

 構建完HttpSecurity例項後,預設情況下會新增預設的攔截其配置:

        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();

 我挑一個預設的方法展開看一下比如 會話管理的sessionManagement(),內部就是去建立SessionManagementConfigurer並應用它

public SessionManagementConfigurer<HttpSecurity> sessionManagement() throws Exception {
    return getOrApply(new SessionManagementConfigurer<>());
}

 getOrApply 最有一句程式碼 return apply(configurer);

private <C extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity>> C getOrApply(
        C configurer) throws Exception {
    C existingConfig = (C) getConfigurer(configurer.getClass());
    if (existingConfig != null) {
        return existingConfig;
    }
    return apply(configurer);
}

 apply(configurer) 注意這裡的 configurer傳入的是SessionManagementConfigurer

public <C extends SecurityConfigurerAdapter<O, B>> C apply(C configurer)
        throws Exception {
    configurer.addObjectPostProcessor(objectPostProcessor);
    configurer.setBuilder((B) this);
    add(configurer);
    return configurer;
}

 最終又呼叫了 add(configurer); 這不過這裡是給 HttpSecurity的 configurers 配置初始的,上面是配置的WebSecurity的configurers, 不要混淆,最終這些configurers會被一個個建立成 對應的過濾器Filter的 詳細在後面有說明

private <C extends SecurityConfigurer<O, B>> void add(C configurer) {
    Assert.notNull(configurer, "configurer cannot be null");

    Class<? extends SecurityConfigurer<O, B>> clazz = (Class<? extends SecurityConfigurer<O, B>>) configurer
            .getClass();
    synchronized (configurers) {
        if (buildState.isConfigured()) {
            throw new IllegalStateException("Cannot apply " + configurer
                    + " to already built object");
        }
        List<SecurityConfigurer<O, B>> configs = allowConfigurersOfSameType ? this.configurers
                .get(clazz) : null;
        if (configs == null) {
            configs = new ArrayList<>(1);
        }
        configs.add(configurer);
        this.configurers.put(clazz, configs);
        if (buildState.isInitializing()) {
            this.configurersAddedInInitializing.add(configurer);
        }
    }
}

 如下圖:為HttpSecurity添加了很多預設的配置

 回到 getHttp()方法

 最後呼叫configure(http);,這又是一個可個性化的配置入口,它的預設實現是:WebSecurityConfigurerAdapter提供的

 預設的配置是攔截所有的請求需要認證之後才能訪問,如果沒有認證,會自動生成一個認證表單要求輸入使用者名稱和密碼。

protected void configure(HttpSecurity http) throws Exception {
    logger.debug("Using default configure(HttpSecurity). If subclassed this will potentially override subclass configure(HttpSecurity).");

    http
        .authorizeRequests()
            .anyRequest().authenticated()
            .and()
        .formLogin().and()
        .httpBasic();
}

 2、個性化配置入口之configure(HttpSecurity http)
 我們可以通過繼承WebSecurityConfigurerAdapter並重寫該方法來個性化配置HttpSecurity。

 OK,目前為止HttpSecurity已經被初始化,接下去需要設定HttpSecurity物件新增至WebSecurity的securityFilterChainBuilders列表中:

public void init(final WebSecurity web) throws Exception {
    final HttpSecurity http = getHttp();
    web.addSecurityFilterChainBuilder(http).postBuildAction(() -> {
        FilterSecurityInterceptor securityInterceptor = http
                .getSharedObject(FilterSecurityInterceptor.class);
        web.securityInterceptor(securityInterceptor);
    });
}

 當所有的WebSecurityConfigurer的init方法被呼叫之後,webSecurity.init()工作就結束了

 接下去呼叫了webSecurity.configure(),該方法同樣是在AbstractConfiguredSecurityBuilder中實現的:

private void configure() throws Exception {
    Collection<SecurityConfigurer<O, B>> configurers = getConfigurers();

    for (SecurityConfigurer<O, B> configurer : configurers) {
        configurer.configure((B) this);
    }
}

 它的主要工作是迭代呼叫所有WebSecurityConfigurer的configurer方法,引數是WebSeucrity本身,這又是另外一個重要的個性化入口:

 3、個性化配置入口之configure(WebSecurity web)
 我們可以通過繼承WebSecurityConfigurerAdapter並重寫該方法來個性化配置WebSecurity。

 至此,三個重要的個性化入口都已經被呼叫,即在實現WebSecurityConfigurerAdapter經常需要重寫的:

1、configure(AuthenticationManagerBuilder auth);

2、configure(WebSecurity web);

3、configure(HttpSecurity http);

 回到webSecurity構建過程,接下去重要的的呼叫:

O result = performBuild();

 performBuild() 非常重要!!

@Override
protected Filter performBuild() throws Exception {
    Assert.state(
            !securityFilterChainBuilders.isEmpty(),
            () -> "At least one SecurityBuilder<? extends SecurityFilterChain> needs to be specified. "
                    + "Typically this done by adding a @Configuration that extends WebSecurityConfigurerAdapter. "
                    + "More advanced users can invoke "
                    + WebSecurity.class.getSimpleName()
                    + ".addSecurityFilterChainBuilder directly");
    int chainSize = ignoredRequests.size() + securityFilterChainBuilders.size();
    List<SecurityFilterChain> securityFilterChains = new ArrayList<>(
            chainSize);
    for (RequestMatcher ignoredRequest : ignoredRequests) {
        securityFilterChains.add(new DefaultSecurityFilterChain(ignoredRequest));
    }
    for (SecurityBuilder<? extends SecurityFilterChain> securityFilterChainBuilder : securityFilterChainBuilders) {
        securityFilterChains.add(securityFilterChainBuilder.build());
    }
    FilterChainProxy filterChainProxy = new FilterChainProxy(securityFilterChains);
    if (httpFirewall != null) {
        filterChainProxy.setFirewall(httpFirewall);
    }
    filterChainProxy.afterPropertiesSet();

    Filter result = filterChainProxy;
    if (debugEnabled) {
        logger.warn("\n\n"
                + "********************************************************************\n"
                + "**********        Security debugging is enabled.       *************\n"
                + "**********    This may include sensitive information.  *************\n"
                + "**********      Do not use in a production system!     *************\n"
                + "********************************************************************\n\n");
        result = new DebugFilter(filterChainProxy);
    }
    postBuildAction.run();
    return result;


}

 首先計算出chainSize,也就是ignoredRequests.size() + securityFilterChainBuilders.size();,如果你不配置ignoredRequests,那就是securityFilterChainBuilders.size(),也就是HttpSecurity的個數,其本質上就是你一共配置幾個WebSecurityConfigurerAdapter,因為每個WebSecurityConfigurerAdapter對應一個HttpSecurity,而所謂的ignoredRequests就是FilterChainProxy的請求,預設是沒有的,如果你需要條跳過某些請求不需要認證或授權,可以如下配置:

@Override
public void configure(WebSecurity web) throws Exception {
    web.ignoring().antMatchers("/statics/**");
}

 在上面配置中,所有以/statics開頭請求都將被FilterChainProxy忽略。

 securityFilterChains.add(securityFilterChainBuilder.build()); 這一行就是初始化所有的過濾器,記得上面有段程式碼如下,將HttpSecurity設定到WebSecurity的 securityFilterChainBuilder中,上面就是呼叫HttpSecurity.build()方法,初始化所有的 HttpSecurity的過濾器鏈

public void init(final WebSecurity web) throws Exception {
    final HttpSecurity http = getHttp();
    web.addSecurityFilterChainBuilder(http).postBuildAction(() -> {
        FilterSecurityInterceptor securityInterceptor = http
                .getSharedObject(FilterSecurityInterceptor.class);
        web.securityInterceptor(securityInterceptor);
    });
}

 依然來到 doBuild()方法,只不過這次是執行的 HttpSecurity的

@Override
protected final O doBuild() throws Exception {
    synchronized (configurers) {
        buildState = BuildState.INITIALIZING;

        beforeInit();
        init();

        buildState = BuildState.CONFIGURING;

        beforeConfigure();
        configure();

        buildState = BuildState.BUILDING;

        O result = performBuild();

        buildState = BuildState.BUILT;

        return result;
    }
}

 重點檢視 configure()該方法 會呼叫對應的 過濾器配置的configure()
如 再內部建立 SessionManagementFilter 最後新增到HttpSecurity中,也就是拿 HttpSecurity的configures 一個個創建出對應的過濾器

@Override
public void configure(H http) {
    SecurityContextRepository securityContextRepository = http
            .getSharedObject(SecurityContextRepository.class);
    SessionManagementFilter sessionManagementFilter = new SessionManagementFilter(
            securityContextRepository, getSessionAuthenticationStrategy(http));
    if (this.sessionAuthenticationErrorUrl != null) {
        sessionManagementFilter.setAuthenticationFailureHandler(
                new SimpleUrlAuthenticationFailureHandler(
                        this.sessionAuthenticationErrorUrl));
    }
    InvalidSessionStrategy strategy = getInvalidSessionStrategy();
    if (strategy != null) {
        sessionManagementFilter.setInvalidSessionStrategy(strategy);
    }
    AuthenticationFailureHandler failureHandler = getSessionAuthenticationFailureHandler();
    if (failureHandler != null) {
        sessionManagementFilter.setAuthenticationFailureHandler(failureHandler);
    }
    AuthenticationTrustResolver trustResolver = http
            .getSharedObject(AuthenticationTrustResolver.class);
    if (trustResolver != null) {
        sessionManagementFilter.setTrustResolver(trustResolver);
    }
    sessionManagementFilter = postProcess(sessionManagementFilter);

    http.addFilter(sessionManagementFilter);
    if (isConcurrentSessionControlEnabled()) {
        ConcurrentSessionFilter concurrentSessionFilter = createConcurrencyFilter(http);

        concurrentSessionFilter = postProcess(concurrentSessionFilter);
        http.addFilter(concurrentSessionFilter);
    }
}

 當doBuild()中的 configure();執行完畢後 的會得到如下HttpSecurity可以看到它內部的filters已經全部建立完畢

 回到doBuild()方法 該方中有 performBuild() 呼叫HttpSecurity的 performBuild(),預設實現如下,先對上面所有的過濾器進行排序,使用的是 FilterComparator() 進行排序的,這裡不展開了,反正就是會排序成文章開始的那張圖上面的順序

@Override
protected DefaultSecurityFilterChain performBuild() {
    filters.sort(comparator);
    return new DefaultSecurityFilterChain(requestMatcher, filters);
}

 最後返回的是SecurityFilterChain的預設實現DefaultSecurityFilterChain。

 構建完所有SecurityFilterChain後,建立最為重要的FilterChainProxy例項,

FilterChainProxy filterChainProxy = new FilterChainProxy(securityFilterChains);

 至此Spring Security 初始化完成,包括springSecurityFilterChain初始化,我們通過繼承WebSecurityConfigurerAdapter來代達到個性化配置目的,文中提到了三個重要的個性化入口,並且WebSecurityConfigurerAdapter是可以配置多個的,其對應的介面就是會存在多個SecurityFilterChain例項,但是它們人仍然在同一個FilterChainProxy中,通過RequestMatcher來匹配並傳入到對應的SecurityFilterChain中執行請求。

 5.個性化入口配置(擴充套件WebSecurityConfigurerAdapter)

 重要的個性化入口都是哪裡呼叫的 已經在上面初始化 springSecurityFilterChain 原始碼中講解了,這裡知識總結一下

 1、個性化配置入口之configure(AuthenticationManagerBuilder auth)

 我們可以通過繼承WebSecurityConfigurerAdapter並重寫該方法來個性化配置AuthenticationManagerBuilder。

 2、個性化配置入口之configure(HttpSecurity http)
 我們可以通過繼承WebSecurityConfigurerAdapter並重寫該方法來個性化配置HttpSecurity。

 3、個性化配置入口之configure(WebSecurity web)
 我們可以通過繼承WebSecurityConfigurerAdapter並重寫該方法來個性化配置WebSecurity。

 實現WebSecurityConfigurerAdapter經常需要重寫的:

1、configure(AuthenticationManagerBuilder auth);

2、configure(WebSecurity web);

3、configure(HttpSecurity http);

 6.總結

 本篇主要講解了
 1.SpringBoot對於SpringSecurity的自動配置的支援類SecurityAutoConfiguration,
 2.核心註解@EnableWebSecurity
 3. SpringSecurity的核心過濾器鏈 springSecurityFilterChain 的初始化流程的原始碼
原始碼部分還是定下心來多看 加油!

個人部落格地址: https://www.askajohnny.com 歡迎訪問!
本文由部落格一文多發平臺 OpenWrite 釋出!