javascript
Spring Security源码解析(四)—— 过滤器
目錄
FilterChainProxy
屬性
構(gòu)造函數(shù)
執(zhí)行Filter
獲取Filter
VirtualFilterChain?
默認(rèn)過(guò)濾器
默認(rèn)Filter
WebAsyncManagerIntegrationFilter
SecurityContextPersistenceFilter
HeaderWriterFilter
CsrfFilter
LogoutFilter
UsernamePasswordAuthenticationFilter
RequestCacheAwareFilter
SecurityContextHolderAwareRequestFilter
AnonymousAuthenticationFilter
SessionManagementFilter
ExceptionTranslationFilter
DefaultSecurityFilterChain
WebSecurity的performBuild()方法,會(huì)構(gòu)造一個(gè)FilterChainProxy實(shí)例。參數(shù)類型為List<SecurityFilterChain>。
FilterChainProxy filterChainProxy = new FilterChainProxy(securityFilterChains);if (httpFirewall != null) {filterChainProxy.setFirewall(httpFirewall);}通過(guò)一個(gè)proxy,封裝所有的Filter。
FilterChainProxy
屬性
public class FilterChainProxy extends GenericFilterBean {private final static String FILTER_APPLIED = FilterChainProxy.class.getName().concat(".APPLIED");private List<SecurityFilterChain> filterChains;private FilterChainValidator filterChainValidator = new NullFilterChainValidator();private HttpFirewall firewall = new StrictHttpFirewall(); }內(nèi)部存儲(chǔ)了一個(gè)SecurityFilterChain列表。
構(gòu)造函數(shù)
主要用于設(shè)置filterChains
public FilterChainProxy() {}public FilterChainProxy(SecurityFilterChain chain) {this(Arrays.asList(chain));}public FilterChainProxy(List<SecurityFilterChain> filterChains) {this.filterChains = filterChains;}執(zhí)行Filter
@Overridepublic void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) throws IOException, ServletException { //T1boolean clearContext = request.getAttribute(FILTER_APPLIED) == null;if (clearContext) {try { //T2request.setAttribute(FILTER_APPLIED, Boolean.TRUE); //T5doFilterInternal(request, response, chain);}finally { //T4SecurityContextHolder.clearContext();request.removeAttribute(FILTER_APPLIED);}}else { //T5doFilterInternal(request, response, chain);}}T1:判斷是否正在進(jìn)行filter,
T2:設(shè)置正在進(jìn)行標(biāo)志。
T4:執(zhí)行清理工作。
T5:執(zhí)行內(nèi)部filter操作。
private void doFilterInternal(ServletRequest request, ServletResponse response,FilterChain chain) throws IOException, ServletException { //T1FirewalledRequest fwRequest = firewall.getFirewalledRequest((HttpServletRequest) request);HttpServletResponse fwResponse = firewall.getFirewalledResponse((HttpServletResponse) response); //T2List<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"));} //T3fwRequest.reset(); //T4chain.doFilter(fwRequest, fwResponse);return;}//T5VirtualFilterChain vfc = new VirtualFilterChain(fwRequest, chain, filters);vfc.doFilter(fwRequest, fwResponse);}T1:包裝請(qǐng)求和響應(yīng)
T2:根據(jù)請(qǐng)求獲取所有Filter,也即獲取請(qǐng)求匹配的Filter。
T3,T4:如果沒有滿足的Filter,則重置請(qǐng)求,并且執(zhí)行指定FilterChain的過(guò)濾操作。
T5:如果有滿足的Filter,則構(gòu)造虛擬過(guò)濾鏈。
獲取Filter
返回第一個(gè)匹配的FilterChain的Filter列表。
private List<Filter> getFilters(HttpServletRequest request) {for (SecurityFilterChain chain : filterChains) {if (chain.matches(request)) {return chain.getFilters();}}return null;} public interface SecurityFilterChain {boolean matches(HttpServletRequest request);List<Filter> getFilters(); }?
VirtualFilterChain?
封裝原始FilterChain和匹配Filters的 FilterChain。
private static class VirtualFilterChain implements FilterChain {private final FilterChain originalChain;private final List<Filter> additionalFilters;private final FirewalledRequest firewalledRequest;private final int size;private int currentPosition = 0;private VirtualFilterChain(FirewalledRequest firewalledRequest,FilterChain chain, List<Filter> additionalFilters) {this.originalChain = chain;this.additionalFilters = additionalFilters;this.size = additionalFilters.size();this.firewalledRequest = firewalledRequest;} } @Overridepublic void doFilter(ServletRequest request, ServletResponse response)throws IOException, ServletException { //如果是最后一個(gè),則調(diào)用原始FilterChain的doFilter,并且調(diào)用不再傳遞。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 chainthis.firewalledRequest.reset();originalChain.doFilter(request, response);}else {currentPosition++; //獲取下一個(gè)Filter。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() + "'");} //調(diào)用傳遞。nextFilter.doFilter(request, response, this);}}默認(rèn)過(guò)濾器
FilterChainProxy接收List<SecurityFilterChain>。即可以通過(guò)自定義Buidler創(chuàng)建,也可以采用默認(rèn)實(shí)現(xiàn)。默認(rèn)實(shí)現(xiàn)
默認(rèn)過(guò)濾器通過(guò)WebSecurityConfigurerAdapter的getHttp()方法進(jìn)行配置。如果沒有禁用默認(rèn)配置,則會(huì)設(shè)置一些默認(rèn)配置。
if (!disableDefaults) {// @formatter:offhttp.csrf().and().addFilter(new WebAsyncManagerIntegrationFilter()).exceptionHandling().and().headers().and().sessionManagement().and().securityContext().and().requestCache().and().anonymous().and().servletApi().and().apply(new DefaultLoginPageConfigurer<>()).and().logout();// @formatter:onClassLoader classLoader = this.context.getClassLoader();List<AbstractHttpConfigurer> defaultHttpConfigurers =SpringFactoriesLoader.loadFactories(AbstractHttpConfigurer.class, classLoader);for(AbstractHttpConfigurer configurer : defaultHttpConfigurers) {http.apply(configurer);}}默認(rèn)Filter
根據(jù)FilterComparator設(shè)置的順序,如下:
WebAsyncManagerIntegrationFilter
提供SecurityContext和spring Web的集成
SecurityContextPersistenceFilter
加載SecurityContext對(duì)象,然后加載到SecurityContextHolder
HeaderWriterFilter
對(duì)響應(yīng)信息的請(qǐng)求頭添加一些配置
CsrfFilter
防止跨站請(qǐng)求偽造
LogoutFilter
對(duì)登出操作的處理
UsernamePasswordAuthenticationFilter
用戶名密碼登錄認(rèn)證
RequestCacheAwareFilter
用于用戶登錄成功后,重新恢復(fù)因?yàn)榈卿洷淮驍嗟恼?qǐng)求
SecurityContextHolderAwareRequestFilter
填充ServletRequest,實(shí)現(xiàn)servlet API安全方法的包裝器
AnonymousAuthenticationFilter
匿名用戶信息的填充
SessionManagementFilter
會(huì)話的管理機(jī)制
ExceptionTranslationFilter
對(duì)于任意的AccessDeniedException類型的異常和AuthenticationException類型異常的處理
DefaultSecurityFilterChain
默認(rèn)SecurityFilterChain,使用指定Matcher匹配,返回所有Filters 。
public final class DefaultSecurityFilterChain implements SecurityFilterChain {private static final Log logger = LogFactory.getLog(DefaultSecurityFilterChain.class);private final RequestMatcher requestMatcher;private final List<Filter> filters;public RequestMatcher getRequestMatcher() {return requestMatcher;}public List<Filter> getFilters() {return filters;}public boolean matches(HttpServletRequest request) {return requestMatcher.matches(request);}}?
總結(jié)
以上是生活随笔為你收集整理的Spring Security源码解析(四)—— 过滤器的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: IDEA同时使用maven和gradle
- 下一篇: gradle idea java ssm