? ? ? ? 繼承Shiro和Spring時愉豺,我們都知道要先通過web.xml部署描述符或者其他方式阔蛉,向ServletContext添加過濾器阵幸。因為要與Spring繼承瓣喊,所以添加的過濾器其實是spring相關的坡慌,也就是DelegatingFilterProxy。
????????DelegatingFilterProxy的所有任務交給Root ApplicationContext這個級別的Spring容器中的一個bean來完成藻三。如果在配置DelegatingFilterProxy過濾器的時候沒有指定targetName屬性八匠,那么DelegatingFilterProxy會去到Spring容器里找id為<filter-name>的bean,所以我們要在Spring容器里配置這樣一個Bean趴酣。從這里開始與Shiro就有關系了。
? ? ? ? 盡管已經知道了id應當是什么坑夯,但是還不清除這個Bean的類型岖寞,它是ShiroFilterFactoryBean。先不理會什么是FactoryBean柜蜈,先看它有哪些屬性仗谆,這關系到可以怎樣配置它指巡。
? ? ? ? 如果你已經在web.xml中配置過ShiroFilterFactoryBean,那么你會對其中的屬性非常熟悉隶垮。它們是如何起作用的呢藻雪。這里就必須清除FactoryBean是什么了。
? ? ? ? 這是ShiroFilterFactoryBean的類圖狸吞。以上兩個接口都是Spring相關的勉耀。這里涉及到Spring中Bean的聲明周期,那是另外一個問題了蹋偏”愠猓總之,當請求一個FactoryBean時威始,得到不是這個類本身的實例枢纠,而是它的getObject()方法返回的對象。那ShiroFilterFactoryBean的getObject方法是什么呢黎棠?它和另一個creatInstance方法直接相關:
? ? ? ? 直接看最后一行晋渺,最終的Bean類型是SpringShiroFilter。它得到兩個參數(shù)脓斩,第一個參數(shù)securityManager正是我們在配置ShiroFilterFactoryBean中指定的木西,第二個參數(shù)的得來非常復雜,現(xiàn)在只需在整體上知道chainResolver能將請求路徑匹配到恰當?shù)倪^濾器鏈俭厚。
? ? ? ? 此次户魏,在web.xml中在DelegatingFilterProxy上設置的過濾路徑,過濾任務交給了<filter-name>指出的bean挪挤,這個bean看上去是ShiroFilterFactoryBean叼丑,實際上卻是SpringShiroFilter。下面開始真正的SpringShiroFilter之旅扛门。
? ? ? ? 從AbstractFilter開始鸠信,在其init(FilterConfig filterConfig)方法中,完成了持有ServletContext的任務论寨。這個方法會在生成過濾器實例時由Servlet容器自動調用星立。
? ? ? ? 從NameableFilter開始,可以在運行過程中重新設置Filter的name屬性葬凳。然后是OncePerRequestFilter绰垂。
? ? ? ? 注意,到現(xiàn)在為止我們仍然是在談論一個過濾器火焰,它的類型是SpringShiroFilter劲装,它在Init方法持有了ServletContext。當恰當?shù)穆窂奖徽埱髸r,它的doFilter方法被Servlet容器調用占业。alreadyFilteredAttributeName其實就是Filter的name屬性绒怨。顯然首次調用時,執(zhí)行的是第二條黑線所示的方法谦疾,這個方法被它的子類AbstractShiroFilter實現(xiàn)南蹂。
? ? ? ? ? ??SpringShiroFilter過濾器執(zhí)行到這一步開始包裝請求念恍,響應六剥,創(chuàng)建Subject了。因為創(chuàng)建Subject和包裝后的request與response相關樊诺,所以先探索如何包裝的request和response仗考。請看起底Shiro(2)