从源码开始精通spring-security1

参考b站up主:传送门

前沿: 本章:spring-security 重要的成员 WebSecurity、HttpSecurity、SecurityBuilder、SecurityFilterChain、FilterChainProxy

重点:WebSecurity、HttpSecurity 他们都实现了 SecurityBuilder 接口 用来构建对象

WebSecurity的作用:

WebSecurity最终是为了构建Filter

首先看下他的结构:

public final class WebSecurity extends
		AbstractConfiguredSecurityBuilder<Filter, WebSecurity> implements
		SecurityBuilder<Filter>, ApplicationContextAware{
    
    
  
}

小插曲:其实WebSecurity继承的AbstractConfiguredSecurityBuilder就已经实现了SecurityBuilder也就是说WebSecurity继承AbstractConfiguredSecurityBuilder就已经能完成工作了,再实现一遍SecurityBuilder什么意思?理解:从看代码的人角度 能够更加清晰的知道WebSecurity实现了SecurityBuilder,是我们最重要的接口而泛型Filter就已经知道要构建的对象是Filter

总之:我们一下子在这就能看到WebSecurity最终构建的对象Object是什么?就是Filter。

写不写implements SecurityBuilder 都能完成工作

HttpSecurity的作用

用刚才WebSecurity的方法来理解

public final class HttpSecurity extends
		AbstractConfiguredSecurityBuilder<DefaultSecurityFilterChain, HttpSecurity>
		implements SecurityBuilder<DefaultSecurityFilterChain>,
		HttpSecurityBuilder<HttpSecurity> {
    
    
      
    }

HttpSecurity是为了构建DefaultSecurityFilterChain对象的。是SecurityFilterChain的默认实现类

SecurityFilterChain

SecurityFilterChain:是一个接口,默认的实现是DefaultSecurityFilterChain

/**
Defines a filter chain which is capable of being matched against an HttpServletRequest. in order to decide whether it applies to that request.
定义这样的一个过滤器链去匹配一个特定的request,然后决定这个request能不能应用这个List<Filter>
*/
public interface SecurityFilterChain {
    
    

	boolean matches(HttpServletRequest request);

	List<Filter> getFilters();
}

SecurityFilterChain也是spring-security当中重要的一个成员。两个方法:

1、matches 是否能匹配 request

2、匹配成功 那么就getFilters()方法所有的Filter都应用一遍

SecurityFilterChain的默认实现

DefaultSecurityFilterChain

public final class DefaultSecurityFilterChain implements SecurityFilterChain {
    
    
  // 在matches中判断能不能匹配request
  private final RequestMatcher requestMatcher;
	private final List<Filter> filters;
  public DefaultSecurityFilterChain(RequestMatcher requestMatcher, Filter... filters) {
    
    
		this(requestMatcher, Arrays.asList(filters));
	}

	public DefaultSecurityFilterChain(RequestMatcher requestMatcher, List<Filter> filters) {
    
    
		logger.info("Creating filter chain: " + requestMatcher + ", " + filters);
		this.requestMatcher = requestMatcher;
		this.filters = new ArrayList<>(filters);
	}

	public RequestMatcher getRequestMatcher() {
    
    
		return requestMatcher;
	}
	// 匹配成功就把Filter应用一遍
	public List<Filter> getFilters() {
    
    
		return filters;
	}
  // 在matches中判断能不能匹配request
  public boolean matches(HttpServletRequest request) {
    
    
		return requestMatcher.matches(request);
	}
}

WebSecurity到底构建了怎样的Filter?

public interface SecurityBuilder<O> {
    
    

   /**
    * Builds the object and returns it or null.
    *
    * @return the Object to be built or null if the implementation allows it.
    * @throws Exception if an error occurred when building the Object
    */
   O build() throws Exception;
}

通过build方法看它的实现:AbstractSecurityBuilder实现了SecurityBuilder接口中的build方法

AbstractSecurityBuilder抽象类中 doBuild方法的构建工作委派给子类实现。

public abstract class AbstractSecurityBuilder<O> implements SecurityBuilder<O>{
    
    
  
  private AtomicBoolean building = new AtomicBoolean();

	private O object;
  //AbstractSecurityBuilder实现了SecurityBuilder接口中的build方法
  public final O build() throws Exception {
    
    
		if (this.building.compareAndSet(false, true)) {
    
    
			this.object = doBuild();
			return this.object;
		}
    // 解决了重复构建问题 如果再构建一次就抛出异常了
		throw new AlreadyBuiltException("This object has already been built");
	}
  // 构建工作 doBuild 方法
  protected abstract O doBuild() throws Exception;
}

继续往下走

AbstractConfiguredSecurityBuilder还是一个抽象类。它实现了父类的doBuild方法

public abstract class AbstractConfiguredSecurityBuilder<O, B extends SecurityBuilder<O>>
		extends AbstractSecurityBuilder<O> {
    
    
  
  
     @Override
      protected final O doBuild() throws Exception {
    
    
        // 加锁 此阶段只能一个线程执行
        synchronized (configurers) {
    
    
          buildState = BuildState.INITIALIZING;
					// 留给子类实现的模版方法  不强制子类实现 即不重要的方法
          beforeInit();
          init();

          buildState = BuildState.CONFIGURING;
					// 留给子类实现的模版方法 不强制子类实现 即不重要的方法
          beforeConfigure();
          configure();

          buildState = BuildState.BUILDING;
					// 重要方法  有三个类实现它 AuthenticationManagerBuilder HttpSecurity WebSecurity
          O result = performBuild();

          buildState = BuildState.BUILT;

          return result;
        }
      } 
  //不强制子类实现
  protected void beforeInit() throws Exception {
    
    
	}
  //不强制子类实现
  protected void beforeConfigure() throws Exception {
    
    
	}
  
  // 重要方法
  protected abstract O performBuild() throws Exception;
  
}

这里通过performBuild();方法构建了我们最终所需要的Object,核心逻辑就在performBuild方法。

有三个类实现它 AuthenticationManagerBuilder、HttpSecurity、 WebSecurity

HttpSecurity的performBuild方法

@Override
	protected DefaultSecurityFilterChain performBuild() {
    
    
		filters.sort(comparator);
		return new DefaultSecurityFilterChain(requestMatcher, filters);
	}

最终返回的就是DefaultSecurityFilterChain 前面说到HttpSecurity所要构建的就是DefaultSecurityFilterChain 那么HttpSecurity的工作完成了。

WebSecurity的performBuild方法

WebSecurity作用:构建一个Filter 显然 构建工作在这

	@Override
	protected Filter performBuild() throws Exception {
    
    
		Assert.state(
				!securityFilterChainBuilders.isEmpty(),
				() -> "At least one SecurityBuilder<? extends SecurityFilterChain> needs to be specified. "
						+ "Typically this done by adding a @Configuration that extends WebSecurityConfigurerAdapter. "
						+ "More advanced users can invoke "
						+ WebSecurity.class.getSimpleName()
						+ ".addSecurityFilterChainBuilder directly");
		int chainSize = ignoredRequests.size() + securityFilterChainBuilders.size();
		List<SecurityFilterChain> securityFilterChains = new ArrayList<>(
				chainSize);
		for (RequestMatcher ignoredRequest : ignoredRequests) {
    
    
			securityFilterChains.add(new DefaultSecurityFilterChain(ignoredRequest));
		}
		for (SecurityBuilder<? extends SecurityFilterChain> securityFilterChainBuilder : securityFilterChainBuilders) {
    
    
			securityFilterChains.add(securityFilterChainBuilder.build());
		}
    // FilterChainProxy 就是Filter的一个变种 最终还是一个Filter
		FilterChainProxy filterChainProxy = new FilterChainProxy(securityFilterChains);
		if (httpFirewall != null) {
    
    
			filterChainProxy.setFirewall(httpFirewall);
		}
		filterChainProxy.afterPropertiesSet();

		Filter result = filterChainProxy;
    //debugEnabled:这个是通过 @EnableWebSecurity(dubug=true)开启的
		if (debugEnabled) {
    
    
			logger.warn("\n\n"
					+ "********************************************************************\n"
					+ "**********        Security debugging is enabled.       *************\n"
					+ "**********    This may include sensitive information.  *************\n"
					+ "**********      Do not use in a production system!     *************\n"
					+ "********************************************************************\n\n");
			result = new DebugFilter(filterChainProxy);
		}
		postBuildAction.run();
		return result;
	}

FilterChainProxy

前置知识:

SecurityFilterChain:就是一个过滤器链 前面介绍过了 这个过滤器链能否应用就跟请求能不能匹配。

public class FilterChainProxy extends GenericFilterBean {
    
    
  
  //传了一堆 SecurityFilterChain
  public FilterChainProxy(List<SecurityFilterChain> filterChains) {
    
    
		this.filterChains = filterChains;
	}
  
  //  是Filter的一个主要方法  doFilter做过滤的 控制过滤器只能执行一次
  @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);
		}
	}
  	
  	//FilterChain tomcat下的一个接口 他的最主要实现是 ApplicationFilterChain
  	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 虚拟的过滤器链  chain 最顶层的过滤器链
    // VirtualFilterChain最终就是 把 这个参数中的 filters 挨个应用一遍
		VirtualFilterChain vfc = new VirtualFilterChain(fwRequest, chain, filters);
    // 虚拟的过滤器链 调用了他的 doFilter方法
		vfc.doFilter(fwRequest, fwResponse);
	}
  
  // 如果应用中定义了多个SecurityFilterChain 如果想要第一个匹配的去执行 此时需要控制一下顺序 实现Order接口 或者Order注解控制?
  private List<Filter> getFilters(HttpServletRequest request) {
    
    
		for (SecurityFilterChain chain : filterChains) {
    
    
      // 匹配到第一个即成功
			if (chain.matches(request)) {
    
    
				return chain.getFilters();
			}
		}

		return null;
	}
  
  		@Override
		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);
			}
		}
	}
}

最后

至此spring-security流程分析完毕 它最顶层就是一个Filter 这个Filter就是FilterChainProxy。

FilterChainProxy里面有一堆的SecurityFilterChain private List<SecurityFilterChain> filterChains;(这个是FilterChainProxy类中的属性),这些SecurityFilterChain都有一个匹配器叫做RequestMatcher,这个RequestMatcher是 SecurityFilterChain的默认实现类DefaultSecurityFilterChain中的属性。

RequestMatcher 是一个接口 有若干个实现 它就是用来匹配请求的。

流程总结:

由FilterChainProxy进来通过调用doFilter方法-进去再调用doFilterInternal方法-通过getFilters 根据HttpServletRequest这个对象去匹配第一个能够匹配的SecurityFilterChain 把其中Filters拿出来。

构建成了一个VirtualFilterChain对象 挨个调用他们的doFilter。

猜你喜欢

转载自blog.csdn.net/qq_43566782/article/details/129353030