shiro 之 封装 filterChainDefinitionMap
在我们之前的学习中有接触过 Shiro 的 DefaultFilter 在整个 Shiro 架构中的作用便是用来拦截所有请求。在 Shiro DefaultFilter 中我们配置了 filterChainDefinitions 属性。filterChainDefinitions 的作用便是对所有被Shiro 拦截的请求做声明,下面看一下一个 标准的 DefaultFilter 和 filterChainDefinitions 的配置。
<!-- 6.配置ShiroFilter 6.1 id必须和web.xml中的DelegatingFilterProxy的 FilterName一致 -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager" />
<property name="loginUrl" value="/login/toLogin" />
<property name="successUrl" value="/example/index" />
<property name="unauthorizedUrl" value="/example/unauthorized" />
<property name="filterChainDefinitions">
<value>
/login/toLogin = anon
/login/loginVal = anon
/login/logout = logout
/example/admin =authc,roles[admin]
/example/admin =authc,perms[admin:view:*]
/example/user = authc,roles[user]
/example/user = authc,perms[user:view:*]
/** = authc
</value>
</property>
</bean>
从以上的配置我们可以预见一个问题,那就是倘若 filterChainDefinitions 的声明过多的话会导致该配置文件冗余臃肿,这对于一个有强迫症的 Dev. 将会是一种很痛苦的折磨,所以我们要配置优雅简洁的 filterChainDefinitions 。
下面我们介绍一种通过工厂设计模式来创建一个 filterChainDefinitionMap。应为在Shiro 的源代码中 filterChainDefinition 本身是一个linkedHashMap
filterChainDefinition
public class ShiroFilterFactoryBean implements FactoryBean, BeanPostProcessor { private static transient final Logger log = LoggerFactory.getLogger(ShiroFilterFactoryBean.class); private SecurityManager securityManager; private Map<String, Filter> filters; private Map<String, String> filterChainDefinitionMap; //urlPathExpression_to_comma-delimited-filter-chain-definition private String loginUrl; private String successUrl; private String unauthorizedUrl; private AbstractShiroFilter instance; public ShiroFilterFactoryBean() { this.filters = new LinkedHashMap<String, Filter>(); this.filterChainDefinitionMap = new LinkedHashMap<String, String>(); //order matters! } }
自定义一个 filterChainDefinitionMap
package com.shiro.example.utils; import java.util.LinkedHashMap; public class FilterChainDefinitionMapBuilder { /** * 自定义 FilterChainDefinition * @return */ public LinkedHashMap<String, String> buildFilterChainDefinitionMap(){ LinkedHashMap<String, String> map = new LinkedHashMap<>(); //此处声明关系也可是已配置在数据库中的 map.put("/login/toLogin", "anon"); map.put("/login/loginVal", "anon"); map.put("/login/logout ", "logout"); map.put("/example/admin", "authc,roles[admin]"); map.put("/example/admin", "authc,perms[admin:view:*]"); map.put("/example/user", "authc,roles[user]"); map.put("/example/user", "authc,perms[user:view:*]"); map.put("/**", "authc"); return map; } }
在配置文件中声明 FilterChainDefinitionMapBuilder
<bean id="filterChainDefinitionMapBuilder"
class="com.shiro.example.utils.FilterChainDefinitionMapBuilder"></bean>
- 在配置文件中声明 filterChainDefinitionMap
<bean id="filterChainDefinitionMap"
factory-bean="filterChainDefinitionMapBuilder"
factorymethod="buildFilterChainDefinitionMap"></bean>
在DefaultFilter中声明 filterChainDefinitionMap
<property name="filterChainDefinitionMap" ref="filterChainDefinitionMap"> <!-- <value> /login/toLogin = anon /login/loginVal = anon /login/logout = logout /example/admin =authc,roles[admin] /example/admin =authc,perms[admin:view:*] /example/user = authc,roles[user] /example/user = authc,perms[user:view:*] /** = authc </value> --> </property>
小结
重新封装filterChainDefinitionMap我们能获得以下益处:
减少配置文件冗余
使 filterChainDefinitionMap 变得高度可配置化并将其从预配置中独立出来,进行单独配置或者后台设置,