前言
上一篇博文主要講了SpringShiroFilter的初始化過程,這篇文章主要解析SpringShir Filter在處理請求時做了些什麼。
概述
SpringShiroFilter處理請求的中心思想是獲取某個請求對應的shiroFilterChain,並新增到javaEE規範的FilterChian中,從而使得配置的過濾器能夠被呼叫,具體怎麼做到的,我們看正文的解析
正文
首先,還是先給出SpringShiroFilter的繼承結構,如下圖:
既然是過濾器,那麼一定是有一個doFilter方法供Servlet容器呼叫(如tomcat),,SpringShiroFilter中沒有這個方法,我們一層一層的的往上找,直到在OncePerRequestFilter中找到該方法
這裡會呼叫到125行的doFilterInternal()方法,該方法是個抽象方法,那麼檢視他的子類AbstractShiroFilter。在第356-359行對request和response進行了處理,以及建立了一個Subject。這裡本篇文章不講述其中的過程。後面會出專門的文章講述。主要涉及到脫離容器的session實現以及Subject的建立。關注到362行,這裡匿名實現了一個callable介面,最終呼叫到365行的excuteChain(),這是整個SpringShiroFilter的核心所在 這裡的邏輯是獲取一個可執行的過濾鏈,並呼叫其doFilter()方法觸發下一個過濾器往下執行。getExecutionChain()方法進一步點進去,這裡第一步409行獲得初始化時注入的FilterChainResolver,第二步415行通過這個解析器獲得初始化時配置好的過濾鏈 點進415行獲取過濾鏈的具體方法,第一步,獲取到請求的URI,第二步,將URI與xml中配置的URL進行逐個比對,第三步對這個匹配的過濾器進行代理(這個很重要)並返回 細看第二步,點進比對方法,這裡把它委託給了初始化時預設的AntPathMarcher,最終實現比較邏輯的是doMatch方法。(所以我們以後要實現shiro相容restFul路徑時應該要重新的就是這個類的該方法,並注入到FilterChainResolver) 回到第三步,點進111行的proxy()方法 繼續點進proxy()方法 這裡返回了一個被包裝了的FilterChain,看看他的doFilter方法。(註釋翻譯:如果封裝好的chain到了末端,那麼開始呼叫原生的過濾鏈)。所以這裡會將shiro的過濾鏈先呼叫完,再執行javaEE規範的過濾鏈。現在完成了最重要的一步,將FilterChain進行了代理,下面一路回退,回退到最開始的executerChain()方法,在得到這個代理過濾鏈後直接呼叫doFilter方法觸發我們配置的具體過濾器。
自此,SpringShiroFilter完成了他的使命--通過組合的方式將shiroFilterChian新增到FilterChian中,所以一旦經過經過了這個過濾器,那麼我們的filterChain可就不是原來的filterChain了,shiro通過組合的設計模式對doFilter()方法的具體實現修改了,並且絲毫不影響客戶端呼叫程式碼,甚至都感知不到原來這個FilterChain已經被shiro"無恥"的篡改了。
本篇文章講了SpringShiroFilter將ShiroFilterChain載入到FilterChain的實現原理,下一篇文章將以PermissionsAuthorizationFilter為例講解具體的ShiroFilter過濾的步驟。