FilterChainProxy內部儲存了我們各個HttpSecurty生成的SecurityFilterChain。FilterChainProxy實現了ServletFilter介面。只真正的入口
org.springframework.security.web.FilterChainProxy.doFilter
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { boolean clearContext = request.getAttribute(FILTER_APPLIED) == null; if (!clearContext) { this.doFilterInternal(request, response, chain); } else { try { request.setAttribute(FILTER_APPLIED, Boolean.TRUE); <1>執行 this.doFilterInternal(request, response, chain); } catch (Exception var11) { Throwable[] causeChain = this.throwableAnalyzer.determineCauseChain(var11); Throwable requestRejectedException = this.throwableAnalyzer.getFirstThrowableOfType(RequestRejectedException.class, causeChain); if (!(requestRejectedException instanceof RequestRejectedException)) { throw var11; } //自定義異常處理器 this.requestRejectedHandler.handle((HttpServletRequest)request, (HttpServletResponse)response, (RequestRejectedException)requestRejectedException); } finally { //清理 SecurityContextHolder.clearContext(); request.removeAttribute(FILTER_APPLIED); } } }
<1>
org.springframework.security.web.FilterChainProxy#doFilterInternal
private void doFilterInternal(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { FirewalledRequest firewallRequest = this.firewall.getFirewalledRequest((HttpServletRequest)request); HttpServletResponse firewallResponse = this.firewall.getFirewalledResponse((HttpServletResponse)response); <2>根據url獲取filters 多登入邏輯實現 List<Filter> filters = this.getFilters((HttpServletRequest)firewallRequest); if (filters != null && filters.size() != 0) { if (logger.isDebugEnabled()) { logger.debug(LogMessage.of(() -> { return "Securing " + requestLine(firewallRequest); })); } VirtualFilterChain virtualFilterChain = new VirtualFilterChain(firewallRequest, chain, filters); //執行filter virtualFilterChain.doFilter(firewallRequest, firewallResponse); } else { if (logger.isTraceEnabled()) { logger.trace(LogMessage.of(() -> { return "No security for " + requestLine(firewallRequest); })); } firewallRequest.reset(); chain.doFilter(firewallRequest, firewallResponse); } }
<2>
org.springframework.security.web.FilterChainProxy#getFilters(javax.servlet.http.HttpServletRequest)
private List<Filter> getFilters(HttpServletRequest request) { int count = 0; Iterator var3 = this.filterChains.iterator(); SecurityFilterChain chain; do { if (!var3.hasNext()) { return null; } chain = (SecurityFilterChain)var3.next(); if (logger.isTraceEnabled()) { ++count; logger.trace(LogMessage.format("Trying to match request against %s (%d/%d)", chain, count, this.filterChains.size())); } } while(!chain.matches(request)); return chain.getFilters(); }