Filter
spring security 是借助于 Filter 过滤器机制来实现的并在过程中结合了spring的机制 那么就从DelegatingFilterProxy开始分析spring security的整体执行流程
1. DelegatingFilterProxy
这个类作为过滤器添加到tomcat的过滤器链中在执行过程会按照顺序执行到这个类
public class DelegatingFilterProxy extends GenericFilterBean {
...
@Nullable
private volatile Filter delegate;// 这个类做为一个连接点
...
}
参看DelegatingFilterProxy的doFilter方法用以设置delegate
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
//懒加载单例模式 防止多个FilterChainProxy实例
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?");
}
//通过这个方法获取到FilterChainProxy实例对象(内部通过WebApplicationContext的getBean方法获取实例对象 通过targetName获取)
delegateToUse = initDelegate(wac);
}
this.delegate = delegateToUse;
}
}
//此方法是调用FilterChainProxy的doFilter方法
invokeDelegate(delegateToUse, request, response, filterChain);
}
protected void invokeDelegate(Filter delegate, ServletRequest request, ServletResponse response, FilterChain filterChain) throws ServletException, IOException {
delegate.doFilter(request, response, filterChain);
}
2.FilterChainProxy
2.1 FilterChainProxy实例化过程
//this.securityFilterChains 成员填充
@Autowired(required = false)
void setFilterChains(List<SecurityFilterChain> securityFilterChains) {
this.securityFilterChains = securityFilterChains;
}
@Bean(name = AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME)
public Filter springSecurityFilterChain() throws Exception {
...
for (SecurityFilterChain securityFilterChain : this.securityFilterChains) {
this.webSecurity.addSecurityFilterChainBuilder(() -> securityFilterChain);
for (Filter filter : securityFilterChain.getFilters()) {
if (filter instanceof FilterSecurityInterceptor) {
this.webSecurity.securityInterceptor((FilterSecurityInterceptor) filter);
break;
}
}
}
...
return this.webSecurity.build();
}
|
V this.webSecurity.build() 创建FilterChianProxy
protected Filter performBuild() throws Exception {
//去掉部分代码
...
//过滤器链列表
List<SecurityFilterChain> securityFilterChains = new ArrayList<>(chainSize);
...
for (SecurityBuilder<? extends SecurityFilterChain> securityFilterChainBuilder : this.securityFilterChainBuilders) {
SecurityFilterChain securityFilterChain = securityFilterChainBuilder.build();
securityFilterChains.add(securityFilterChain);
...
}
...
//初始化过滤器代理的过滤器链用以在执行流程中执行
FilterChainProxy filterChainProxy = new FilterChainProxy(securityFilterChains);
filterChainProxy.afterPropertiesSet();
Filter result = filterChainProxy;
...
this.postBuildAction.run();
return result;
}
2.2 Spring Security 过滤器链
2.3 FilterChainProxy执行过程
FilterChainProxy 作为spring security的一个重要执行中转类会从spring ioc 中获取到所有的 spring security的过滤器并添加到内部filters成员中
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
boolean clearContext = request.getAttribute(FILTER_APPLIED) == null;
if (!clearContext) {
doFilterInternal(request, response, chain);
return;
}
try {
request.setAttribute(FILTER_APPLIED, Boolean.TRUE);
doFilterInternal(request, response, chain);
}catch (RequestRejectedException ex) {
this.requestRejectedHandler.handle((HttpServletRequest) request, (HttpServletResponse) response, ex);
}
finally {
SecurityContextHolder.clearContext();
request.removeAttribute(FILTER_APPLIED);
}
}
|
V
private void doFilterInternal(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
FirewalledRequest firewallRequest = this.firewall.getFirewalledRequest((HttpServletRequest) request);
HttpServletResponse firewallResponse = this.firewall.getFirewalledResponse((HttpServletResponse) response);
//获取 securityFilterChains 列表中的所有过滤器
List<Filter> filters = getFilters(firewallRequest);
//如果过滤器链列表为空或者没有过滤器则调用会调用ApplicationFilterChain.doFilter方法
if (filters == null || filters.size() == 0) {
firewallRequest.reset();
chain.doFilter(firewallRequest, firewallResponse);
return;
}
...
//虚拟过滤器链 - 此处是spring security过滤器
VirtualFilterChain virtualFilterChain = new VirtualFilterChain(firewallRequest, chain, filters);
virtualFilterChain.doFilter(firewallRequest, firewallResponse);
}
3. VirtualFilterChain
VirtualFilterChain 类构造方法
private VirtualFilterChain(FirewalledRequest firewalledRequest, FilterChain chain,
List<Filter> additionalFilters) {
this.originalChain = chain; //ApplicationFilterChain
this.additionalFilters = additionalFilters; //spring security过滤器列表
this.size = additionalFilters.size();
this.firewalledRequest = firewalledRequest;
}
VirtualFilterChina 类doFilter方法
public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException {
if (this.currentPosition == this.size) {
if (logger.isDebugEnabled()) {
logger.debug(LogMessage.of(() -> "Secured " + requestLine(this.firewalledRequest)));
}
// Deactivate path stripping as we exit the security filter chain
this.firewalledRequest.reset();
this.originalChain.doFilter(request, response);
return;
}
//currentPosition全局变量是过滤器列表的偏移每执行一次当前类的doFilter方法都会+1
this.currentPosition++;
Filter nextFilter = this.additionalFilters.get(this.currentPosition - 1);
//调用过滤器链中过滤器 过滤器链列表在上图2.2
//传入当前this对象 用以下一个过滤器调用doFilter方法并回到此处
nextFilter.doFilter(request, response, this);
}