相关阅读
简介
FilterChainResolver
可以在ServletRequest
请求过程中解析正确的过滤器链去执行,允许为任意请求或者URI/URL解析可以执行的任意过滤器链;
这种过滤器解析机制比通过web.xml定义servlet过滤器的方式更加灵活;
核心方法
/**
* 获取给定request的过滤器链
* 返回值为null,表示使用原始过滤器链
*/
FilterChain getChain(ServletRequest request, ServletResponse response, FilterChain originalChain);
实现子类
public interface FilterChainResolver
public class PathMatchingFilterChainResolver implements FilterChainResolver
PathMatchingFilterChainResolver
简介
根据URL路径匹配,解析出ServletRequest
请求过程中要执行的过滤器链;
核心方法
// 过滤器链管理器
private FilterChainManager filterChainManager;
// 路径匹配器
private PatternMatcher pathMatcher;
// 默认路径分隔符
private static final String DEFAULT_PATH_SEPARATOR = "/";
/**
* 构造方法
*/
public PathMatchingFilterChainResolver() {
// 默认为AntPathMatcher
this.pathMatcher = new AntPathMatcher();
// 默认为DefaultFilterChainManager
this.filterChainManager = new DefaultFilterChainManager();
}
/**
* 构造方法
*/
public PathMatchingFilterChainResolver(FilterConfig filterConfig) {
// 默认为AntPathMatcher
this.pathMatcher = new AntPathMatcher();
// 默认为DefaultFilterChainManager
this.filterChainManager = new DefaultFilterChainManager(filterConfig);
}
/**
* 获取给定request的过滤器链
* 返回值为null,表示使用原始过滤器链
*/
public FilterChain getChain(ServletRequest request, ServletResponse response, FilterChain originalChain) {
FilterChainManager filterChainManager = getFilterChainManager();
if (!filterChainManager.hasChains()) {
// 无配置,则使用原始过滤器链
return null;
}
// 获取应用程序内的URI的相对路径
final String requestURI = getPathWithinApplication(request);
// 去除URL路径结尾处分隔符
final String requestURINoTrailingSlash = removeTrailingSlash(requestURI);
// 遍历配置的管理器链
//the 'chain names' in this implementation are actually path patterns defined by the user. We just use them
//as the chain name for the FilterChainManager's requirements
for (String pathPattern : filterChainManager.getChainNames()) {
// If the path does match, then pass on to the subclass implementation for specific checks:
if (pathMatches(pathPattern, requestURI)) {
if (log.isTraceEnabled()) {
log.trace("Matched path pattern [{}] for requestURI [{}]. " +
"Utilizing corresponding filter chain...", pathPattern, Encode.forHtml(requestURI));
}
// 代理原始过滤器链,即先执行配置的Shiro过滤器链,再执行原始过滤器链
return filterChainManager.proxy(originalChain, pathPattern);
} else {
// in spring web, the requestURI "/resource/menus" ---- "resource/menus/" bose can access the resource
// but the pathPattern match "/resource/menus" can not match "resource/menus/"
// user can use requestURI + "/" to simply bypassed chain filter, to bypassed shiro protect
// 对配置的路径去除结尾处分隔符,再进行一次匹配
pathPattern = removeTrailingSlash(pathPattern);
if (pathMatches(pathPattern, requestURINoTrailingSlash)) {
if (log.isTraceEnabled()) {
log.trace("Matched path pattern [{}] for requestURI [{}]. " +
"Utilizing corresponding filter chain...", pathPattern, Encode.forHtml(requestURINoTrailingSlash));
}
// 代理原始过滤器链,即先执行配置的Shiro过滤器链,再执行原始过滤器链
return filterChainManager.proxy(originalChain, requestURINoTrailingSlash);
}
}
}
// 无配置,则使用原始过滤器链
return null;
}
/**
* 路径匹配
*/
protected boolean pathMatches(String pattern, String path) {
PatternMatcher pathMatcher = getPathMatcher();
return pathMatcher.matches(pattern, path);
}
/**
* 获取应用程序内的URI的相对路径
*/
protected String getPathWithinApplication(ServletRequest request) {
return WebUtils.getPathWithinApplication(WebUtils.toHttp(request));
}
/**
* 去除URL路径结尾处分隔符
*/
private static String removeTrailingSlash(String path) {
if(path != null && !DEFAULT_PATH_SEPARATOR.equals(path)
&& path.endsWith(DEFAULT_PATH_SEPARATOR)) {
return path.substring(0, path.length() - 1);
}
return path;
}