7.SpringSecurity-基本原理(过滤器加载过程)

  使用SpringSecurity配置过滤器DelegatingFilterProxy;
在这里插入图片描述
  本质上来说DelegatingFilterProxy就是一个Filter,其间接实现了Filter接口,但是在doFilter中其实调用的从Spring 容器中获取到的代理Filter的实现类delegate。

DelegatingFilterProxy原理

  DelegatingFilterProxy根据targetBeanName从Spring 容器中获取被注入到Spring 容器的Filter实现类,在DelegatingFilterProxy配置时一般需要配置属性targetBeanName

@Override
protected void initFilterBean() throws ServletException {
	synchronized (this.delegateMonitor) {
		if (this.delegate == null) {
			// If no target bean name specified, use filter name.
                        //当Filter配置时如果没有设置targentBeanName属性,则直接根据Filter名称来查找
			if (this.targetBeanName == null) {
				this.targetBeanName = getFilterName();
			}
			// Fetch Spring root application context and initialize the delegate early,
			// if possible. If the root application context will be started after this
			// filter proxy, we'll have to resort to lazy initialization.
			WebApplicationContext wac = findWebApplicationContext();
			if (wac != null) {
                                //从Spring容器中获取注入的Filter的实现类
				this.delegate = initDelegate(wac);
			}
		}
	}
}
 
protected Filter initDelegate(WebApplicationContext wac) throws ServletException {
   //从Spring 容器中获取注入的Filter的实现类
   String targetBeanName = getTargetBeanName();
   Assert.state(targetBeanName != null, "No target bean name set");
   Filter delegate = wac.getBean(targetBeanName, Filter.class);
   if (isTargetFilterLifecycle()) {
      delegate.init(getFilterConfig());
   }
   return delegate;
}

  在DelegatingFilterProxy的实现方法doFilter中,其实最终调用的是委派的类delegate

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
      throws ServletException, IOException {

   // Lazily initialize the delegate if necessary.
   Filter delegateToUse = this.delegate;
   if (delegateToUse == null) {
      synchronized (this.delegateMonitor) {
         delegateToUse = this.delegate;
         if (delegateToUse == null) {
            WebApplicationContext wac = findWebApplicationContext();
            if (wac == null) {
               throw new IllegalStateException("No WebApplicationContext found: " +
                     "no ContextLoaderListener or DispatcherServlet registered?");
            }
            delegateToUse = initDelegate(wac);
         }
         this.delegate = delegateToUse;
      }
   }

   // Let the delegate perform the actual doFilter operation.
   invokeDelegate(delegateToUse, request, response, filterChain);
}




protected Filter initDelegate(WebApplicationContext wac) throws ServletException {
   //从Spring 容器中获取注入的Filter的实现类的名称,叫做FilterChainProxy
   String targetBeanName = getTargetBeanName();
   Assert.state(targetBeanName != null, "No target bean name set");
   Filter delegate = wac.getBean(targetBeanName, Filter.class);
   if (isTargetFilterLifecycle()) {
      delegate.init(getFilterConfig());
   }
   return delegate;
}

  在FilterChainProxy中的doFilter方法中,最终去调用了doFilterInternal方法:

@Override
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下级方法
private void doFilterInternal(ServletRequest request, ServletResponse response,
      FilterChain chain) throws IOException, ServletException {

   FirewalledRequest fwRequest = firewall
         .getFirewalledRequest((HttpServletRequest) request);
   HttpServletResponse fwResponse = firewall
         .getFirewalledResponse((HttpServletResponse) response);
    //filters中包含着过滤器链中的多个过滤器
   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(fwRequest, fwResponse);
}




//getFilters下级方法:
private List<Filter> getFilters(HttpServletRequest request) {
    //SecurityFilterChain就是最底层的接口
   for (SecurityFilterChain chain : filterChains) {
      if (chain.matches(request)) {
         return chain.getFilters();
      }
   }

   return null;
}

  filters:
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值