package com.hwlcn.security.web.filter; import com.hwlcn.security.util.AntPathMatcher; import com.hwlcn.security.util.PatternMatcher; import com.hwlcn.security.util.StringUtils; import com.hwlcn.security.web.servlet.AdviceFilter; import com.hwlcn.security.web.util.WebUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.servlet.Filter; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import java.util.LinkedHashMap; import java.util.Map; public abstract class PathMatchingFilter extends AdviceFilter implements PathConfigProcessor { private static final Logger log = LoggerFactory.getLogger(PathMatchingFilter.class); protected PatternMatcher pathMatcher = new AntPathMatcher(); protected Map<String, Object> appliedPaths = new LinkedHashMap<String, Object>(); public Filter processPathConfig(String path, String config) { String[] values = null; if (config != null) { values = StringUtils.split(config); } this.appliedPaths.put(path, values); return this; } protected String getPathWithinApplication(ServletRequest request) { return WebUtils.getPathWithinApplication(WebUtils.toHttp(request)); } protected boolean pathsMatch(String path, ServletRequest request) { String requestURI = getPathWithinApplication(request); if (log.isTraceEnabled()) { log.trace("Attempting to match pattern '{}' with current requestURI '{}'...", path, requestURI); } return pathsMatch(path, requestURI); } protected boolean pathsMatch(String pattern, String path) { return pathMatcher.matches(pattern, path); } protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception { if (this.appliedPaths == null || this.appliedPaths.isEmpty()) { if (log.isTraceEnabled()) { log.trace("appliedPaths property is null or empty. This Filter will passthrough immediately."); } return true; } for (String path : this.appliedPaths.keySet()) { if (pathsMatch(path, request)) { if (log.isTraceEnabled()) { log.trace("Current requestURI matches pattern '{}'. Determining filter chain execution...", path); } Object config = this.appliedPaths.get(path); return isFilterChainContinued(request, response, path, config); } } return true; } private boolean isFilterChainContinued(ServletRequest request, ServletResponse response, String path, Object pathConfig) throws Exception { if (isEnabled(request, response, path, pathConfig)) { if (log.isTraceEnabled()) { log.trace("Filter '{}' is enabled for the current request under path '{}' with config [{}]. " + "Delegating to subclass implementation for 'onPreHandle' check.", new Object[]{getName(), path, pathConfig}); } return onPreHandle(request, response, pathConfig); } if (log.isTraceEnabled()) { log.trace("Filter '{}' is disabled for the current request under path '{}' with config [{}]. " + "The next element in the FilterChain will be called immediately.", new Object[]{getName(), path, pathConfig}); } return true; } protected boolean onPreHandle(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception { return true; } protected boolean isEnabled(ServletRequest request, ServletResponse response, String path, Object mappedValue) throws Exception { return isEnabled(request, response); } }