Spring Security的過濾鏈工作原理
阿新 • • 發佈:2018-12-22
上一篇文章中提到了名為springSecurityFilterChain的bean在Spring容器中的註冊過程。它所代表的類即為org.springframework.security.web.FilterChainProxy.
所以所有的url請求實際上都會經過這個過濾器代理。讓我們檢視一下他的doFilter方法
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { boolean clearContext = request.getAttribute(FILTER_APPLIED) == null; if(clearContext) { try { request.setAttribute(FILTER_APPLIED, Boolean.TRUE); doFilterInternal(request, response, chain); } finally { SecurityContextHolder.clearContext(); request.removeAttribute(FILTER_APPLIED); } } else { doFilterInternal(request, response, chain); } }
由此可見,他會再次經過doFilterInternal 方法
由此可見,他的下一步就是走VirtualFilterChain 的doFilter方法private void doFilterInternal(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { FirewalledRequest fwRequest = firewall.getFirewalledRequest((HttpServletRequest) request); HttpServletResponse fwResponse = firewall.getFirewalledResponse((HttpServletResponse) response); 這個getFilters方法得到的過濾器就是在進行配置檔案解析時,security元件註冊的一些過濾器 List<Filter> filters = getFilters(fwRequest); //如果得到的過濾器的數量為零,則直接跳過 if (filters == null || filters.size() == 0) { if (logger.isDebugEnabled()) { logger.debug(UrlUtils.buildRequestUrl(fwRequest) + (filters == null ? " has no matching filters" : " has an empty filter list")); } fwRequest.reset(); chain.doFilter(fwRequest, fwResponse); return; } VirtualFilterChain vfc = new VirtualFilterChain(fwRequest, chain, filters); //請求轉入vfc的doFilter方法 vfc.doFilter(fwRequest, fwResponse); }
public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException { if (currentPosition == size) { if (logger.isDebugEnabled()) { logger.debug(UrlUtils.buildRequestUrl(firewalledRequest) + " reached end of additional filter chain; proceeding with original chain"); } // Deactivate path stripping as we exit the security filter chain this.firewalledRequest.reset(); originalChain.doFilter(request, response); } else { currentPosition++; 此實現就是一個過濾鏈的一個實現方式 Filter nextFilter = additionalFilters.get(currentPosition - 1); if (logger.isDebugEnabled()) { logger.debug(UrlUtils.buildRequestUrl(firewalledRequest) + " at position " + currentPosition + " of " + size + " in additional filter chain; firing Filter: '" + nextFilter.getClass().getSimpleName() + "'"); } nextFilter.doFilter(request, response, this); } }