shiro框架源码解析与改造(五)---SpringShiroFilter

这个类继承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);

猜你喜欢

转载自blog.csdn.net/ljz2016/article/details/81214957
今日推荐