Shiro FilterChain的设计概念
FilterChainManager
其行为有:
其主要职责就是增,查Filter、增,查Chain
DefaultFilterChainManager
其具备javax.servlet.FilterConfig(过滤器配置)、Map<String, Filter> filters(过滤器集合)、Map<String, NamedFilterList> filterChains(过滤器链集合)
构造器中添加Shiro的默认过滤器
public DefaultFilterChainManager() { this.filters = new LinkedHashMap<String, Filter>(); this.filterChains = new LinkedHashMap<String, NamedFilterList>(); addDefaultFilters(false); } protected void addDefaultFilters(boolean init) { for (DefaultFilter defaultFilter : DefaultFilter.values()) { addFilter(defaultFilter.name(), defaultFilter.newInstance(), init, false); } } protected void addFilter(String name, Filter filter, boolean init, boolean overwrite) { Filter existing = getFilter(name); if (existing == null || overwrite) { if (filter instanceof Nameable) { ((Nameable) filter).setName(name); } if (init) { initFilter(filter); } this.filters.put(name, filter); } }
添加Chain到filterChains集合中
public void createChain(String chainName, String chainDefinition) { if (!StringUtils.hasText(chainName)) { throw new NullPointerException("chainName cannot be null or empty."); } if (!StringUtils.hasText(chainDefinition)) { throw new NullPointerException("chainDefinition cannot be null or empty."); } if (log.isDebugEnabled()) { log.debug("Creating chain [" + chainName + "] from String definition [" + chainDefinition + "]"); } // 切割字符串切出chain和filter String[] filterTokens = splitChainDefinition(chainDefinition); for (String token : filterTokens) { String[] nameConfigPair = toNameConfigPair(token); // 添加chain到集合中 addToChain(chainName, nameConfigPair[0], nameConfigPair[1]); } } public void addToChain(String chainName, String filterName, String chainSpecificFilterConfig) { if (!StringUtils.hasText(chainName)) { throw new IllegalArgumentException("chainName cannot be null or empty."); } Filter filter = getFilter(filterName); if (filter == null) { throw new IllegalArgumentException("There is no filter with name '" + filterName + "' to apply to chain [" + chainName + "] in the pool of available Filters. Ensure a " + "filter with that name/path has first been registered with the addFilter method(s)."); } applyChainConfig(chainName, filter, chainSpecificFilterConfig); // 确保有Chain并将Chain添加到filterChains集合中 NamedFilterList chain = ensureChain(chainName);
// chain中加入Filter chain.add(filter); } protected NamedFilterList ensureChain(String chainName) { NamedFilterList chain = getChain(chainName); if (chain == null) { chain = new SimpleNamedFilterList(chainName); this.filterChains.put(chainName, chain); } return chain; }
Manager具备Filter的集合和FilterChain的集合,其中FilterChain还具备Filter集合
FilterChainResolver
其行为有:
PathMatchingFilterChainResolver
其具备了FilterChainManager(过滤器链管理器)和PatternMatcher(路径匹配器)
public FilterChain getChain(ServletRequest request, ServletResponse response, FilterChain originalChain) { FilterChainManager filterChainManager = getFilterChainManager(); // 通过FilterManager是否有FilterChain if (!filterChainManager.hasChains()) { return null; } String requestURI = getPathWithinApplication(request); // 通过FilterManager获得ChainName即路径匹配器的Pattern for (String pathPattern : filterChainManager.getChainNames()) { // 路径匹配了才返回FilterChain if (pathMatches(pathPattern, requestURI)) { if (log.isTraceEnabled()) { log.trace("Matched path pattern [" + pathPattern + "] for requestURI [" + requestURI + "]. " + "Utilizing corresponding filter chain..."); }
// 返回FilterChain的代理 return filterChainManager.proxy(originalChain, pathPattern); } } return null; }
public FilterChain proxy(FilterChain original, String chainName) { NamedFilterList configured = getChain(chainName); if (configured == null) { String msg = "There is no configured chain under the name/key [" + chainName + "]."; throw new IllegalArgumentException(msg); } return configured.proxy(original); }
包装FilterChain
public FilterChain proxy(FilterChain orig) { return new ProxiedFilterChain(orig, this); }
获得requestURI
WebUtils.getPathWithinApplication(HttpServletRequest request);
路径匹配Demo(天下文章一大抄,Shiro就有抄袭Spring的地方)
package com.wjz.demo; import org.apache.shiro.util.AntPathMatcher; public class AntPathMatcherDemo { private static final String pattern = "/admin/**"; public static void main(String[] args) { AntPathMatcher matcher = new AntPathMatcher(); Boolean isMatched = matcher.match(pattern, "/admin/list.do"); System.out.println(isMatched); } }
ProxiedFilterChain
具备了FilterChain和Filter集合
public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException { // 判断filter是否是FilterChain的最后一个Filter if (this.filters == null || this.filters.size() == this.index) { //we've reached the end of the wrapped chain, so invoke the original one: if (log.isTraceEnabled()) { log.trace("Invoking original filter chain."); } // FilterChain执行doFilter this.orig.doFilter(request, response); } else { if (log.isTraceEnabled()) { log.trace("Invoking wrapped filter at index [" + this.index + "]"); } // 获得第index个Filter执行doFilter this.filters.get(this.index++).doFilter(request, response, this); } }
设计概念
对应关系
/admin/list.do=loginFilter,user为FilterChain(Entry),/admin/list.do为Chain name(String),loginFilter,user为Chain(NamedFilterList)
核心类
org.apache.shiro.web.filter.mgt.FilterChainManager
职责是解析xml文件关于shiroFilter的配置信息获得java.servlet.Filter和FilterChain(java.util.LinkedHashMap.Entry),存储Shiro的默认Filter和解析xml获得的Filter,存储FilterChain(这其中还会有创建Chain(org.apache.shiro.web.filter.mgt.NamedFilterList)的行为),包装javax.servlet.FilterChain
org.apache.shiro.web.filter.mgt.NamedFilterList
职责是存储Chain Name,存储javax.servlet.Filter,包装javax.servlet.FilterChain为org.apache.shiro.web.servlet.ProxiedFilterChain
org.apache.shiro.web.filter.mgt.FilterChainResolver
职责是获得javax.servlet.FilterChain,过程为FilterChainManager.proxy(javax.servlet.FilterChain,String chainName) ==> NamedFilterList.proxy(javax.servlet.FilterChain,String chainName) ==> Result:org.apache.shiro.web.servlet.ProxiedFilterChain
org.apache.shiro.util.PatternMatcher
职责是判断requestURI是否与chainName匹配