SpringSecurity 初始化流程源碼

SpringSecurity 初始化流程源碼


SpringSecurity 初始化流程源碼

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


 1.簡單介紹


 SpringSecurity 的核心功能主要包括:

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

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


SpringSecurity 初始化流程源碼


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


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


SocialAuthenticationFilter
比如這個就是社交登錄使用的Filter 詳細可以看我另外一篇 SpringSocial 實現第三方QQ登錄
https://www.askajohnny.com/#/blog/123

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


 2.SecurityAutoConfiguration


 如果是SpringBoot項目只要你依賴了SpringSecurity相關依賴依然會有自動配置類

SecurityAutoConfiguration 生效 它會導入
WebSecurityEnableConfiguration

SpringSecurity 初始化流程源碼

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

SpringSecurity 初始化流程源碼


 3.@EnableWebSecurity註解介紹

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

 打開@EnableWebSecurity註解

<code>    

@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 {/<code>
<code>    /**
     * Controls debugging support 

for

Spring Security. Default is

false

. * @

return

if

true

, enables

debug

support with Spring Security */ boolean

debug

() default

false

; } /<code>

 該註解類通過@Configuration和@Import配合使用引入了一個配置類(WebSecurityConfiguration)和兩個ImportSelector(


SpringWebMvcImportSelector,OAuth2ImportSelector),我們重點關注下WebSecurityConfiguration,它是Spring Security的核心

 4.springSecurityFilterChain初始化流程及源碼

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

<code>     
     (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(); }/<code>

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

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


<code>     (required = 

false

)

public

void

setFilterChainProxySecurityConfigurer

( ObjectPostProcessor objectPostProcessor, @Value(

"#{@autowiredWebSecurityConfigurersIgnoreParents.getWebSecurityConfigurers()}"

)

List> webSecurityConfigurers)

throws

Exception

{ webSecurity = objectPostProcessor .postProcess(

new

WebSecurity(objectPostProcessor));

if

(debugEnabled !=

null

) { webSecurity.debug(debugEnabled); }/<code>
<code>        

webSecurityConfigurers

.sort

(

AnnotationAwareOrderComparator

.INSTANCE

);/<code>
<code>        Integer previousOrder = 

null

; Object previousConfig =

null

;

for

(SecurityConfigurer 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 webSecurityConfigurer : webSecurityConfigurers) { webSecurity.apply(webSecurityConfigurer); }

this

.webSecurityConfigurers = webSecurityConfigurers; }/<code>

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

<code>    webSecurity = objectPostProcessor
                .postProcess(

new

WebSecurity(objectPostProcessor)); /<code>


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

<code>    @Value(

"

#{@autowiredWebSecurityConfigurersIgnoreParents.getWebSecurityConfigurers()}

"

) /<code>

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


<code>    

public

List> getWebSecurityConfigurers() { List> webSecurityConfigurers =

new

ArrayList<>(); Map beansOfType = beanFactory .getBeansOfType(WebSecurityConfigurer

.

class

)

;

for

(Entry entry : beansOfType.entrySet()) { webSecurityConfigurers.add(entry.getValue()); }

return

webSecurityConfigurers; } /<code>

再回到
setFilterChainProxySecurityConfigurer方法 下面有一段這樣的代碼 ,對於上面獲取的所有的WebSecurityConfigurer類型 循環執行 webSecurity的apply方法

<code>    

for

(SecurityConfigurer

webSecurityConfigurer

: webSecurityConfigurers) {

webSecurity

.apply

(webSecurityConfigurer); } /<code>

webSecurity集成
AbstractConfiguredSecurityBuilder 它提供apply方法 再其內部調用add方法

<code>    

public

>

C

apply

(

C configurer

) throws Exception

{

add

(configurer);

return

configurer; } /<code>

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

<code>    

private

>

void

add

(C configurer)

{ Assert.notNull(configurer,

"configurer cannot be null"

);/<code>
<code>        Class extends SecurityConfigurer> clazz = (Class extends SecurityConfigurer>) configurer
                .getClass();
        synchronized (configurers) {
            

if

(buildState.isConfigured()) {

throw

new

IllegalStateException(

"Cannot apply "

+ configurer +

" to already built object"

); } List> 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); } } }/<code>

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


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

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

<code>     (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(); } /<code>

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

<code>     
    

protected

final

O

doBuild

()

throws

Exception

{

synchronized

(configurers) { buildState = BuildState.INITIALIZING;/<code>
<code>            

beforeInit

();

init

();/<code>
<code>            

buildState

= BuildState.CONFIGURING;/<code>
<code>            

beforeConfigure

();

configure

();/<code>
<code>            

buildState

= BuildState.BUILDING;/<code>
<code>            

O

result = performBuild();/<code>
<code>            

buildState

= BuildState.BUILT;/<code>
<code>            

return

result; } }/<code>

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

<code>    

private

void

init

()

throws

Exception

{ Collection> configurers = getConfigurers();/<code>
<code>        

for

(SecurityConfigurer configurer : configurers) { configurer.

init

((B)

this

); }/<code>
<code>        

for

(SecurityConfigurer configurer : configurersAddedInInitializing) { configurer.

init

((B)

this

); } }/<code>

configurer.init((B) this)

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

初始化HttpSecurity對象(注意它和WebSecurity不一樣 );

設置HttpSecurity對象添加至WebSecurity的
securityFilterChainBuilders列表中;


<code>    

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()方法中實現:/<code>
<code>    

protected

final

HttpSecurity

getHttp

()

throws

Exception

{

if

(http !=

null

) {

return

http; }/<code>
<code>        DefaultAuthenticationEventPublisher eventPublisher = objectPostProcessor
                .postProcess(

new

DefaultAuthenticationEventPublisher()); localConfigureAuthenticationBldr.authenticationEventPublisher(eventPublisher);/<code>
<code>        AuthenticationManager authenticationManager = authenticationManager();
        authenticationBuilder.parentAuthenticationManager(authenticationManager);
        authenticationBuilder.authenticationEventPublisher(eventPublisher);
        

Map

,

Object

> sharedObjects = createSharedObjects();/<code>
<code>        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 defaultHttpConfigurers = SpringFactoriesLoader.loadFactories(AbstractHttpConfigurer

.

class

,

classLoader

);

/<code>
<code>            

for

(AbstractHttpConfigurer

configurer

: defaultHttpConfigurers) {

http

.apply

(configurer); } }

configure

(http);

return

http

; } /<code>

 從代碼中可以瞭解,HttpSecurity是直接被new出來的,在創建HttpSecurity之前,首先初始化了
AuthenticationManagerBuilder對象,這裡有段代碼很重要就是: AuthenticationManager authenticationManager = authenticationManager();,它創建AuthenticationManager實例,打開authenticationManager()方法:

 默認實現是在
WebSecurityConfigurerAdapter 中

<code>    

protected

void

configure

(AuthenticationManagerBuilder auth)

throws

Exception

{

this

.disableLocalConfigureAuthenticationBldr =

true

; }/<code>

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

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

SpringSecurity 初始化流程源碼

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

<code>     
    

@Configuration

@Slf4j

public class MyWebSecurityConfig extends WebSecurityConfigurerAdapter { /<code>
<code>     
    

protected

void

configure

(AuthenticationManagerBuilder auth)

throws

Exception

{

super

.configure(auth); log.info(

"【測試 定製化入口 configure(AuthenticationManagerBuilder auth) 的執行 】"

); } }/<code>

 構建完HttpSecurity實例後,默認情況下會添加默認的攔截其配置:

<code>            

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

();/<code>

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

<code>    

public

SessionManagementConfigurer

sessionManagement

()

throws

Exception

{

return

getOrApply(

new

SessionManagementConfigurer<>()); }/<code>

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

<code>    

private

>

C

getOrApply

( C configurer)

throws

Exception

{ C existingConfig = (C) getConfigurer(configurer.getClass());

if

(existingConfig !=

null

) {

return

existingConfig; }

return

apply(configurer); }/<code>

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

<code>    

public

>

C

apply

(

C configurer

) throws Exception

{ configurer.addObjectPostProcessor(objectPostProcessor); configurer.setBuilder((B)

this

);

add

(configurer);

return

configurer; }/<code>

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

<code>    

private

>

void

add

(C configurer)

{ Assert.notNull(configurer,

"configurer cannot be null"

);/<code>
<code>        Class extends SecurityConfigurer> clazz = (Class extends SecurityConfigurer>) configurer
                .getClass();
        synchronized (configurers) {
            

if

(buildState.isConfigured()) {

throw

new

IllegalStateException(

"Cannot apply "

+ configurer +

" to already built object"

); } List> 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添加了很多默認的配置 ![Xnip20200118_205631.png](http: /<code>

 回到 getHttp()方法

 最後調用configure(http);,這又是一個可個性化的配置入口,它的默認實現是:
WebSecurityConfigurerAdapter提供的

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

<code>    

protected

void

configure

(HttpSecurity http)

throws

Exception

{ logger.debug(

"Using default configure(HttpSecurity). If subclassed this will potentially override subclass configure(HttpSecurity)."

);/<code>
<code>        

http

.authorizeRequests

()

.anyRequest

()

.authenticated

()

.and

()

.formLogin

()

.and

()

.httpBasic

(); }/<code>

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

 OK,目前為止HttpSecurity已經被初始化,接下去需要設置HttpSecurity對象添加至WebSecurity的
securityFilterChainBuilders列表中:


<code>    

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); }); } /<code>

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

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

<code>    

private

void

configure

()

throws

Exception

{ Collection> configurers = getConfigurers();/<code>
<code>        

for

(SecurityConfigurer

configurer

: configurers) {

configurer

.configure

((B) this); } } /<code>

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

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

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

<code>    

1

configure

(AuthenticationManagerBuilder auth);/<code>
<code>    

2

configure

(WebSecurity web);/<code>
<code>    

3

configure

(HttpSecurity http);/<code>

 回到webSecurity構建過程,接下去重要的的調用:

<code>    

O

result = performBuild(); /<code>

performBuild() 非常重要!!


<code>    @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 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();/<code>
<code>

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;

/<code>
<code>    }
/<code>

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

<code>     
    

public

void

configure

(WebSecurity web)

throws

Exception

{ web.ignoring().antMatchers(

"/statics/**"

); }  在上面配置中,所有以/statics開頭請求都將被FilterChainProxy忽略。 /<code>

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


<code>    

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); }); } /<code>

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

<code>     
    

protected

final

O

doBuild

()

throws

Exception

{

synchronized

(configurers) { buildState = BuildState.INITIALIZING;/<code>
<code>            

beforeInit

();

init

();/<code>
<code>            

buildState

= BuildState.CONFIGURING;/<code>
<code>            

beforeConfigure

();

configure

();/<code>
<code>            

buildState

= BuildState.BUILDING;/<code>
<code>            

O

result = performBuild();/<code>
<code>            

buildState

= BuildState.BUILT;/<code>
<code>            

return

result; } }/<code>

 重點查看 configure()該方法 會調用對應的 過濾器配置的configure()如 再內部創建 SessionManagementFilter 最後添加到HttpSecurity中,也就是拿 HttpSecurity的configures 一個個創建出對應的過濾器

SpringSecurity 初始化流程源碼

<code>     
    

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);/<code>
<code>        

http.addFilter(sessionManagementFilter);

if

(isConcurrentSessionControlEnabled()) {

ConcurrentSessionFilter

concurrentSessionFilter = createConcurrencyFilter(http);

/<code>
<code>            

concurrentSessionFilter

=

postProcess(concurrentSessionFilter);

http.addFilter(concurrentSessionFilter);

}

}

/<code>

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

SpringSecurity 初始化流程源碼

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


<code>     
    

protected

DefaultSecurityFilterChain

performBuild

()

{ filters.sort(comparator);

return

new

DefaultSecurityFilterChain(requestMatcher, filters); }/<code>

 最後返回的是SecurityFilterChain的默認實現
DefaultSecurityFilterChain。

 構建完所有SecurityFilterChain後,創建最為重要的FilterChainProxy實例,

<code>    FilterChainProxy filterChainProxy = 

new

FilterChainProxy(securityFilterChains);/<code>
SpringSecurity 初始化流程源碼

 至此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經常需要重寫的:

<code>    

1

configure

(AuthenticationManagerBuilder auth);/<code>
<code>    

2

configure

(WebSecurity web);/<code>
<code>    

3

configure

(HttpSecurity http); /<code>

 6.總結

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


個人博客網站
https://www.askajohnny.com 歡迎訪問!

本文由博客一文多發平臺 https://openwrite.cn?from=article_bottom 發佈!


分享到:


相關文章: