前言
shiro是apche的一個開源許可權框架,本人學習的同時準備記錄一下閱讀原始碼的過程,出一個關於shiro的原始碼解析系列文章,其中主要包括過濾器,Subject的建立與維護,Session的管理,登入授權的流程,快取管理。同時熟悉這些之後再基於shiro來進行改造以適應於restful以及jwtToken的技術方案
誰適合讀本篇文章
如果您從未使用過shiro,那麼本篇文章可能不適合您(shiro使用教程友情跳轉:shiro.apache.org/documentati…),本文假設讀者已經掌握了shiro的基本使用,並想進一步探索shiro的原理。
本文的內容總覽
本篇為該系列的第一章,解析shiro過濾器的實現原理,主要分為兩個部分,第一部分解析spring啟動時shiro過濾器的初始化過程,第二部分解析前端發起一個請求後端過濾器許可權驗證的流程。由於篇幅過長,本文僅講解第一部分:Filter的初始化過程。第二部分Filter的過濾流程見下一篇博文
Filter的初始化
這個部分巨集觀上來講,只做了一個工作,就是構建了ShiroFilter。首先給出shiroFilter的配置檔案spring-shiro.xml
1、首先根據spring-shiro.xml的配置作為入口,看看這個Filter是如何構建出來的。(本文的示例工程程式碼地址:github.com/liuruojing/…) 2、這是一個Filter工廠類,所以找到他建立例項的方法。同時需要注意一下他的成員變數,filters是自定義的過濾器,filterChainDefinitionMap是過濾鏈的配置,loginUrl是登入地址,這些都是在spring-shiro.xml中配置的 注:174行開始建立過濾鏈管理器3、點選方法,看看是如何建立這個過濾鏈管理器的,主要包含三步:
1、新增預設的過濾器
2、新增自定義的過濾器
3、構建過濾鏈
回到第3步的371行,這裡為每個filter設定了一些我們配置的引數
回到第3步的376-389行,將我們自定義的攔截器初始化配置並新增到DefaultFilterChainManager中,至此,我們的所有過濾器們(包括預設的以及我們自定義的)已經全部初始化完了,都存在DefaultFilterChainManager中。
4、繼續看392行,現在開始初始化FilterChains(構建過濾鏈) 這裡392行獲取我們所配置的許可權列表,例如(/user/**=authc,perms[user:add,user:delete],這裡等號左邊表路徑,perms是攔截器名稱,user:add是需要的許可權),這裡開始遍歷map,解析每條配置
點進397行createChain(url,"authc,perms[user:add,user:delete]")方法,在第140行首先對authc,perms[user:add,user:delete]進行切分,切分後結果為string[0]=authc,string[1]=perms[user:add,user:delete],然後在144行對切分後的字串迴圈遍歷進行操作,以perms[user:add,user:delete]為例。145行返回string[0]=perms,string[1]=user:add,user:delete。最後呼叫148行新增過濾鏈,chainName=url,nameConfigPair[0]為過濾器名,nameConfigPair[1]為過濾器針對這個url的配置
點進148行的addToChain方法,方法中263行得到對應的過濾器,270行將配置加到filter裡,這裡就是對user:add,user:delete解析的過程 過濾器配置完後,272行確認一下是否有對應的過濾器連結串列,沒有的話新建一個,然後將新的過濾器新增到連結串列尾部 一步一步的解析完所有的許可權配置後,最終如filterChains資料結構,這裡debug看到結果,最終渲染成如下的資料結構 畫出對應的資料結構圖如下 那麼假如現在有個請求訪問/user/add,呼叫filterChainManager.getchain("urlName")就會返回一個匹配的NamedFilterList過濾鏈。6、可以看到,這樣就建立了url與過濾器之間的關聯。既然url已經與過濾鏈進行了關聯,那麼我們在處理時只需要將請求的url與我們配置的url進行一個逐條比對,就可以獲取到這個過濾鏈了。可見我們還需要一個PathMacher(路徑比對器),現在回到第2步中的175-176行,這裡他為我們new了一個PathMatchingFilterChainResolver,看看這個類,構造方法裡面就有了一個預設的AntMathMatcher(這是一個ant風格的路徑匹配器),並把filterChainManager注入到了裡面,對上層呼叫者提供了一層封裝,呼叫者只需要調永chainResolver.getChain(request)就可以獲取到這個請求對應的過濾鏈了。
最後,將這個filterChainResolver注入到Filter中,完成了Filter的構建。下面給出四個主要類的具體類圖
自此,shiroFilter已經初始化完畢,這個初始化過程中主要是構建了一個過濾鏈,提供了一個getChain()方法來獲得過濾鏈。第二部分將講解某一個請求後端過濾器許可權驗證的流程,具體解析獲取過濾鏈,如何執行過濾鏈,以及自定義過濾器被呼叫的過濾方法等等