Spring Security url 攔截匹配規則 深入研究


Spring Security 可以為 url 設置各種訪問規則,比如:

http.authorizeRequests().antMatchers("/api/**").denyAll();    //拒絕訪問

http.authorizeRequests().antMatchers("/api/**").authenticated();    //需認證通過

http.authorizeRequests().antMatchers("/api/**").permitAll();    //無條件允許訪問

 

但是遇到下面這些情況,SpringSecurity會如何處理呢?

1、一個url可以匹配多個規則:如 /api/bbb/ccc  這個url ,既可以匹配 /** ,又可以匹配 /api/**,最終會匹配哪條規則呢?

2、存在相同url 的匹配規則,如上面例子中 "/api/**" 一共有三條規則,一個denyAll,一個authenticated,一個permitAll ,最終會匹配哪條規則呢?

 

讓我們深入代碼弄清楚這些問題【版本 SpringSecurity 5.0.7】:

 

每注冊一個規則  antMatchers("/api/**").xxx()  時,

SpringSecurity會把這個規則按注冊先后順序放到一個ArrayList<UrlMapping>中,先注冊的規則放前面,后注冊的放后面。

然后將這個 ArrayList<UrlMapping> 進行處理( AbstractConfigAttributeRequestMatcherRegistry.createRequestMap 方法)

處理的規則是這樣: 按順序遍歷這個ArrayList,以 url的RequestMatcher 為 key ,以 denyAll,authenticated 等 為值, put 進一個 LinkedHashMap

這個 LinkedHashMap 就是最終的 規則集合。

 

此時,有訪問請求Web服務器,

Web服務器從request中取出訪問的url。

通過之前得到的那個 LinkedHashMap 去 對 url 進行權限判斷,第一個能匹配上這個url的規則,就是最終會執行的規則。(DefaultFilterInvocationSecurityMetadataSource.getAttributes 方法)

 

上面的內容可能看起來有點暈,簡單說就是:

1、注冊的規則 按先后順序放到一個List, 然后又用Map去掉完全相同的 url匹配規則。這個Map 就是最終的規則存放處。

2、當有訪問到來時,則根據訪問的url 循環這個 Map 進行匹配,能匹配上的第一個規則就是 最終執行的規則。

 

然后回到我們上面提出的兩個問題:

1、一個url可以匹配多個規則:如 /api/bbb/ccc  這個url ,既可以匹配 /** ,又可以匹配 /api/**,最終會匹配哪條規則呢?

解答:按你注冊規則的順序,第一條能匹配上的,就是最終會執行的規則。

延伸:注冊規則的時候一定要注意順序,如果 /** 第一個注冊,則后面的任何規則都不會被匹配了,永遠執行 /** 的這個規則。

 

2、存在相同url 的匹配規則,如上面例子中 "/api/**" 一共有三條規則,一個denyAll,一個authenticated,一個permitAll ,最終會匹配哪條規則呢?

解答:在 ArrayList 轉 LinkedHashMap 時,相同的url 的匹配規則中 后面的會沖掉 前面的, 所以,最終執行的規則會是最后注冊的那條

 

最后看一個實際的例子:

注冊完規則的那個 LinkedHashMap :

一共注冊了9條規則,我們注意到有三條相同的url 的匹配規則

最后轉成 LinkedHashMap 后:

Map中只有7條規則了,因為之前9條中的3條規則 url 相同,被處理掉了。

 /Dev/** 是 第3,第7,第9 注冊的,當合並時, 用的第9的值是好理解的,但要特別注意,它在 Map中的順序是第3的位置,過濾優先級很高的。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM