因爲公司要求我對我司的框架的權限模塊進行整理,因此最近看了Shiro這個框架的源碼,裏面有一些思想仍是很是值得學習的,記錄一下java
官網提供了不少種權限的demo,提供web、spring支持、AspectJ、Guice等,因爲筆者技術有限,那麼我先從手洗的Spring開始說web
先送上官網的配置demospring
<!-- Define the realm you want to use to connect to your back-end security datasource: --> <bean id="myRealm" class="..."> ... </bean> <bean id="securityManager" class="org.apache.shiro.mgt.DefaultSecurityManager"> <!-- Single realm app. If you have multiple realms, use the 'realms' property instead. --> <property name="realm" ref="myRealm"/> </bean>
首先說一下realm
,他是獲取一個用戶的信息,其中裏面包括權限,角色等信息,securityManager
爲管理整個權限的對象apache
<!-- The filter-name matches name of a 'shiroFilter' bean inside applicationContext.xml --> <filter> <filter-name>shiroFilter</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> <init-param> <param-name>targetFilterLifecycle</param-name> <param-value>true</param-value> </init-param> </filter> ... <!-- Make sure any request you want accessible to Shiro is filtered. /* catches all --> <!-- requests. Usually this filter mapping is defined first (before all others) to --> <!-- ensure that Shiro works in subsequent filters in the filter chain: --> <filter-mapping> <filter-name>shiroFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
DelegatingFilterProxy
爲提供的filter類,因此它確定會找一個代理的實際對象,在這裏能,他會找filter-name
的bean id進行代理app
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> <property name="securityManager" ref="securityManager"/> <property name="loginUrl" value="/login.jsp"/> <property name="successUrl" value="/home.jsp"/> <property name="filters"> <util:map> <entry key="anAlias" value-ref="someFilter"/> </util:map> </property> <property name="filterChainDefinitions"> <value> # some example chain definitions: /admin/** = authc, roles[admin] /docs/** = authc, perms[document:read] /** = authc # more URL-to-FilterChain definitions here </value> </property> </bean>
shiroFilter
代理的就是這個filter,那麼咱們來分析一下,瞭解過shiro的就不說簡單的了,就特別說一下filters和filterChainDefinitions框架
filters shiro已經提供了默認的filter的了,因此你不少時候均可以看到一些例如,authc、rols、perms、anon等等這樣的配置前綴,那麼這些都說shiro本身默認提供的 固然你能夠經過本身實現Filter接口而後配置到filters中,key就是那個前綴jsp
filterChainDefinitions 這個過濾連比較重要了,首先說明一下,以匹配優先,也就是說,自上而下,若是上面的路徑匹配上了,後面的就不會執行的了。 那麼「=
」號左邊的是請求鏈,固然這個匹配器能夠改的,這些shiro都爲咱們想得很周到,匹配了會採用filters下配的key對應的filter進行處理,可是呢,shiro只處理兩種,這兩種分別是,要麼沒有中括號,要麼有一箇中括號,下面就是解析結果ide
foo returned[0] == foo returned[1] == null foo[bar, baz] returned[0] == foo returned[1] == bar, baz
那麼咱們如今知道怎麼用了,接下來解讀一下源碼:學習
因爲
ShiroFilterFactoryBean
是如今Spring中的FactoryBean
那麼最後確定會調用getObject
方法,那麼他最終仍是採用SecurityManager來建立一個Filter,建立Filter以前,有一個FilterChainManager,過濾連的一個管理者,那麼這個東西里面默認是shiro的提供的Filter,除了默認的filter,他會添加咱們在xml配置的filter,而且在會在filterChainDefinitions
的時候進行解析,而且添加到FilterChainManager中進行管理ui
到目前爲止,已經成功建立了一個SpringShiroFilter
因爲SpringShiroFilter
繼承了AbstractShiroFilter,那麼最終會執行doFilterInternal方法,那麼這個方法裏面也執行了executeChain,這裏就是執行這個過濾的入口 他裏面採用了代理的關係,怎麼說呢?
FilterChainResolver
就是作這個事情的,在建立Security的時候已經產生了,這個類就是產生FilterChain的,那麼再給回去調用FilterChain.doFilter
那麼咱們下面說一下他是怎麼獲取FilterChain的,首先他是依賴FilterChainManager的 那麼來到這裏就已經很明顯了,因爲FilterChainManager都把Filter準備好了,很明顯,在它在Filter的時候已經添加了一個包裝了一下,把解析的那些都放在裏面了,那麼匹配上了,直接獲取出來,最後看下包裝後是怎麼執行的
那麼整個過程大概就是這樣子