web.xml的配置
<filter> <filter-name>shiroFilter</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> <init-param> <!-- 是否進行下一個過濾鏈,默認false --> <param-name>targetFilterLifecycle</param-name> <param-value>true</param-value> </init-param> </filter>
涉及到的Spring部分:DelegatingFilterProxy
我們可以看到起繼承了java.servlet.Filter,這里使用到了委派設計模式,實現了Filter,又具備了Filter,filter的實現方法中使用filter去執行,委派設計模式
Filter的行為
init方法對應着initFilterBean方法
@Override protected void initFilterBean() throws ServletException { synchronized (this.delegateMonitor) { if (this.delegate == null) { // 獲得filter-name的值即 shiroFilter if (this.targetBeanName == null) { this.targetBeanName = getFilterName(); } // 獲得SpringContext上下文 WebApplicationContext wac = findWebApplicationContext(); if (wac != null) { // 初始化下一個Filter this.delegate = initDelegate(wac); } } } } protected Filter initDelegate(WebApplicationContext wac) throws ServletException { // 根據beanName(shiroFilter)和Filter(java.servlet.Filter)類型從上下文中獲得ShiroFilterBean Filter delegate = wac.getBean(getTargetBeanName(), Filter.class); // 是否初始化下一個Filter過濾器 if (isTargetFilterLifecycle()) { delegate.init(getFilterConfig()); } return delegate; }
applicationContext-shiro.xml的配置
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> <property name="securityManager" ref="securityManager" /> <property name="loginUrl" value="/login.do" /> <property name="successUrl" value="/welcome.do" /> <!-- 自定義shiro的Filter --> <property name="filters"> <map> <entry key="loginFilter" value-ref="loginFilter"></entry> </map> </property> <!--基本系統級別權限配置--> <property name="filterChainDefinitions" > <value> /goods/list.do = loginFilter, user /static/** = anno /admin/** = anon </value> </property> </bean> <bean id="loginFilter" class="com.wjz.filter.LoginFilter"/>
shiroFilter對應的是ShiroFilterFactoryBean
ShiroFilterFactoryBean
其實現了FactoryBean,當從上下文中獲得Bean時會走getObject()方法
public Object getObject() throws Exception { if (instance == null) { instance = createInstance(); } return instance; } protected AbstractShiroFilter createInstance() throws Exception { log.debug("Creating Shiro Filter instance."); // 獲得注入進來的SecurityManager SecurityManager securityManager = getSecurityManager(); if (securityManager == null) { String msg = "SecurityManager property must be set."; throw new BeanInitializationException(msg); } if (!(securityManager instanceof WebSecurityManager)) { String msg = "The security manager does not implement the WebSecurityManager interface."; throw new BeanInitializationException(msg); } // 創建過濾器管理器 FilterChainManager manager = createFilterChainManager(); // 創建過濾器解析器 PathMatchingFilterChainResolver chainResolver = new PathMatchingFilterChainResolver(); // 為過濾器解析器注入過濾器管理器 chainResolver.setFilterChainManager(manager); // 創建一個具體的ShiroFilter實例,將SecurityManager和FilterChainResolver注入進去 return new SpringShiroFilter((WebSecurityManager) securityManager, chainResolver); }
ShiroFilterFactoryBean$SpringShiroFilter
構造器
protected SpringShiroFilter(WebSecurityManager webSecurityManager, FilterChainResolver resolver) { super(); if (webSecurityManager == null) { throw new IllegalArgumentException("WebSecurityManager property cannot be null."); } // 為ShiroFilter注入SecurityManager setSecurityManager(webSecurityManager); if (resolver != null) { // 為ShiroFilter注入過濾器解析器 setFilterChainResolver(resolver); } }
Spring調用shiro的Filter的初始化方法:init(FilterConfig filterConfig)方法
public final void init(FilterConfig filterConfig) throws ServletException { // 注入FilterConfig和ServletContext setFilterConfig(filterConfig); try { // 執行FilterConfig注入過程中的行為 onFilterConfigSet(); } catch (Exception e) { if (e instanceof ServletException) { throw (ServletException) e; } else { if (log.isErrorEnabled()) { log.error("Unable to start Filter: [" + e.getMessage() + "].", e); } throw new ServletException(e); } } }
AbstractShiroFilter中
protected final void onFilterConfigSet() throws Exception { // 校驗web.xml中是否配置了staticSecurityManagerEnabled的屬性值,有的話則注入 applyStaticSecurityManagerEnabledConfig(); // 空方法 init(); // 確保SecurityManager已經注入 ensureSecurityManager(); // 如果配置的屬性值為true則為SecurityUtils注入SecurityManager if (isStaticSecurityManagerEnabled()) { SecurityUtils.setSecurityManager(getSecurityManager()); } }