博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Spring Security 过滤流程
阅读量:6295 次
发布时间:2019-06-22

本文共 4970 字,大约阅读时间需要 16 分钟。

hot3.png

通过Debug,最原始的过滤器链是Tomcat的ApplicationFilterChain。

org.apache.catalina.core.ApplicationFilterChain     implements javax.servlet.FilterChain {        // 实例是一个 DispatchServlet    private Servlet servlet;    // 过滤器数组    private ApplicationFilterConfig[] filters = new ApplicationFilterConfig[0];    // 当前的过滤器位置    private int pos;    // 过滤器总数        private int n;    public void doFilter(ServletRequest request, ServletResponse response) {        internalDoFilter(request,response);    }        private void internalDoFilter(ServletRequest request, ServletResponse response) {        if (pos < n) {            ApplicationFilterConfig filterConfig = filters[pos++];            Filter filter = filterConfig.getFilter();            filter.doFilter(request, response, this);        }    }}

这里面有6个过滤器,分别是

0 ApplicationFilterConfig[name=characterEncodingFilter, filterClass=org.springframework.boot.web.servlet.filter.OrderedCharacterEncodingFilter]1 ApplicationFilterConfig[name=hiddenHttpMethodFilter, filterClass=org.springframework.boot.web.servlet.filter.OrderedHiddenHttpMethodFilter]2 ApplicationFilterConfig[name=httpPutFormContentFilter, filterClass=org.springframework.boot.web.servlet.filter.OrderedHttpPutFormContentFilter]3 ApplicationFilterConfig[name=requestContextFilter, filterClass=org.springframework.boot.web.servlet.filter.OrderedRequestContextFilter]4 ApplicationFilterConfig[name=springSecurityFilterChain, filterClass=org.springframework.boot.web.servlet.DelegatingFilterProxyRegistrationBean$1]5 ApplicationFilterConfig[name=Tomcat WebSocket (JSR356) Filter, filterClass=org.apache.tomcat.websocket.server.WsFilter]

Spring boot 以“springSecurityFilterChain”为名字,向容器注入DelegatingFilterProxyRegistrationBean,这个bean被包装成ApplicationFilterConfig, 以便通过getFilter()获取Filter。

这里应该是动态代理(这个暂时没想清楚),当调用filter.doFilter的时候,这个filter实际上是DelegatingFilterProxy。

public class DelegatingFilterProxy extends GenericFilterBean {	private volatile Filter delegate;	public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) {	 	Filter delegateToUse = this.delegate;		invokeDelegate(delegateToUse, request, response, filterChain);	}		protected void invokeDelegate(			Filter delegate, ServletRequest request, ServletResponse response, FilterChain filterChain)			throws ServletException, IOException {		delegate.doFilter(request, response, filterChain);	}}

这里的 delegate 毫无疑问是 FilterChainProxy。

FilterChainProxy就带着一开始的ApplicationFilterChain,开始自己的过滤生涯,doFilter...

public class FilterChainProxy extends GenericFilterBean {	public void doFilter(ServletRequest request, ServletResponse response,			FilterChain chain) throws IOException, ServletException {			doFilterInternal(request, response, chain);	}		private void doFilterInternal(ServletRequest request, ServletResponse response,			FilterChain chain) throws IOException, ServletException {				// wrap		FirewalledRequest fwRequest = firewall				.getFirewalledRequest((HttpServletRequest) request);		HttpServletResponse fwResponse = firewall				.getFirewalledResponse((HttpServletResponse) response);					// 根据请求匹配	security 过滤器		List
filters = getFilters(fwRequest); // 如果没有配置 security 过滤器 if (filters == null || filters.size() == 0) { // reset fwRequest.reset(); // 那么继续原始的过滤器链 ApplicationFilterChain chain.doFilter(fwRequest, fwResponse); } VirtualFilterChain vfc = new VirtualFilterChain(fwRequest, chain, filters); vfc.doFilter(fwRequest, fwResponse); }}

没错,FilterChainProxy根据请求,匹配到好多security过滤器,并用他们创建出一条新的过滤链 VirtualFilterChain。

private static class VirtualFilterChain implements FilterChain {        // 原始的 ApplicationFilterChain	private final FilterChain originalChain;		// security filters	private final List
additionalFilters; private final FirewalledRequest firewalledRequest; private final int size; private int currentPosition = 0; v @Override public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException { // VirtualFilterChain 过滤完成 if (currentPosition == size) { // reset this.firewalledRequest.reset(); // 继续原始链 originalChain.doFilter(request, response); } // 执行过滤器 else { currentPosition++; Filter nextFilter = additionalFilters.get(currentPosition - 1); nextFilter.doFilter(request, response, this); } }}

而这条新过滤链的过滤器数组,正是

additionalFilters = {ArrayList@6631}  size = 13 0 = {WebAsyncManagerIntegrationFilter@6634}  1 = {SecurityContextPersistenceFilter@6471}  2 = {HeaderWriterFilter@6470}  3 = {CsrfFilter@6469}  4 = {LogoutFilter@6468}  5 = {CustomUsernamePasswordAuthenticationFilter@6467}  6 = {UsernamePasswordAuthenticationFilter@6466}  7 = {RequestCacheAwareFilter@6465}  8 = {SecurityContextHolderAwareRequestFilter@6462}  9 = {AnonymousAuthenticationFilter@6458}  10 = {SessionManagementFilter@6457}  12 = {FilterSecurityInterceptor@6635}  11 = {ExceptionTranslationFilter@6455}

转载于:https://my.oschina.net/u/3035165/blog/1926354

你可能感兴趣的文章
solrCloud+tomcat+zookeeper集群配置
查看>>
/etc/fstab,/etc/mtab,和 /proc/mounts
查看>>
Apache kafka 简介
查看>>
socket通信Demo
查看>>
技术人员的焦虑
查看>>
js 判断整数
查看>>
mongodb $exists
查看>>
js实现页面跳转的几种方式
查看>>
sbt笔记一 hello-sbt
查看>>
常用链接
查看>>
pitfall override private method
查看>>
!important 和 * ----hack
查看>>
聊天界面图文混排
查看>>
控件的拖动
查看>>
svn eclipse unable to load default svn client的解决办法
查看>>
Android.mk 文件语法详解
查看>>
QT liunx 工具下载
查看>>
内核源码树
查看>>
AppScan使用
查看>>
Java NIO框架Netty教程(三) 字符串消息收发(转)
查看>>