这个类继承AbstractShiroFilter ,我在这里对notFilter字段做了实现,在shiro域中划了一块方外之地,减少了Subject的创建。
private static final class SpringShiroFilter extends AbstractShiroFilter {
private Set<String> notFilters=new HashSet<>();
protected PatternMatcher pathMatcher = new AntPathMatcher();
protected SpringShiroFilter(WebSecurityManager webSecurityManager, FilterChainResolver resolver, Set<String> notFilters) {
if(webSecurityManager == null) {
throw new IllegalArgumentException("WebSecurityManager property cannot be null.");
} else {
this.setSecurityManager(webSecurityManager);
this.notFilters=notFilters;
if(resolver != null) {
this.setFilterChainResolver(resolver);
}
}
}
@Override
protected boolean shouldNotFilter(ServletRequest request) throws ServletException {
Set<String> notFilters=this.notFilters;
if (notFilters!=null){
Iterator iterator = notFilters.iterator();
String path;
do {
if(!iterator.hasNext()) {
return false;
}
path = (String)iterator.next();
} while(!this.pathsMatch(path, request));
return true;
}
return super.shouldNotFilter(request);
}
protected boolean pathsMatch(String path, ServletRequest request) {
String requestURI = this.getPathWithinApplication(request);
log.trace("Attempting to match pattern '{}' with current requestURI '{}'...");
return this.pathsMatch(path, requestURI);
}
protected String getPathWithinApplication(ServletRequest request) {
return WebUtils.getPathWithinApplication(WebUtils.toHttp(request));
}
protected boolean pathsMatch(String pattern, String path) {
return this.pathMatcher.matches(pattern, path);
}
@Override
public void destroy() {
}
}
在父类中有2个成员变量:
private WebSecurityManager securityManager;
private FilterChainResolver filterChainResolver;
doFilter方法是拦截的起点。
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
String alreadyFilteredAttributeName = this.getAlreadyFilteredAttributeName();
if(request.getAttribute(alreadyFilteredAttributeName) != null) {
filterChain.doFilter(request, response);
}else if(this.isEnabled(request, response) && !this.shouldNotFilter(request)) {
request.setAttribute(alreadyFilteredAttributeName, Boolean.TRUE);
try {
this.doFilterInternal(request, response, filterChain);
} finally {
request.removeAttribute(alreadyFilteredAttributeName);
}
} else {
filterChain.doFilter(request, response);
}
}
实际调用doFilterInternal方法。
this.doFilterInternal(request, response, filterChain);
protected void doFilterInternal(ServletRequest servletRequest, ServletResponse servletResponse, final FilterChain chain) throws ServletException, IOException {
Throwable t = null;
try {
final ServletRequest request = this.prepareServletRequest(servletRequest, servletResponse, chain);
final ServletResponse response = this.prepareServletResponse(request, servletResponse, chain);
// System.out.println(WebUtils.getRequestUri((HttpServletRequest) request));
Subject subject = this.createSubject(request, response);
subject.execute(new Callable() {
public Object call() throws Exception {
AbstractShiroFilter.this.updateSessionLastAccessTime(request, response);
AbstractShiroFilter.this.executeChain(request, response, chain);
return null;
}
});
} catch (ExecutionException var8) {
t = var8.getCause();
} catch (Throwable var9) {
t = var9;
}
if(t != null) {
if(t instanceof ServletException) {
throw (ServletException)t;
} else if(t instanceof IOException) {
throw (IOException)t;
} else {
String msg = "Filtered request failed.";
throw new ServletException(msg, t);
}
}
}
执行拦截链前对request 和response做了包装,然后创建了Subject,在subect的回调函数中执行了filterChain。
protected void executeChain(ServletRequest request, ServletResponse response, FilterChain origChain) throws IOException, ServletException {
FilterChain chain = this.getExecutionChain(request, response, origChain);
chain.doFilter(request, response);
}
protected FilterChain getExecutionChain(ServletRequest request, ServletResponse response, FilterChain origChain) {
FilterChain chain = origChain;
FilterChainResolver resolver = this.getFilterChainResolver();
if(resolver == null) {
log.debug("No FilterChainResolver configured. Returning original FilterChain.");
return origChain;
} else {
FilterChain resolved = resolver.getChain(request, response, origChain);
if(resolved != null) {
log.trace("Resolved a configured FilterChain for the current request.");
chain = resolved;
} else {
log.trace("No FilterChain configured for the current request. Using the default.");
}
return chain;
}
}
上面的filterChainResolver就是上文解析的那个类。
下面的代码是为了保证每一个过滤器在一次请求中只执行一次。
String alreadyFilteredAttributeName = this.getAlreadyFilteredAttributeName();
request.setAttribute(alreadyFilteredAttributeName, Boolean.TRUE);
request.removeAttribute(alreadyFilteredAttributeName);