参考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。