Python微信订餐小程序课程视频
https://edu.csdn.net/course/detail/36074
Python实战量化交易理财系统
https://edu.csdn.net/course/detail/35475
一.前言
spring security安全框架作为spring系列组件中的一个,被广泛的运用在各项目中,那么spring security在程序中的工作流程是个什么样的呢,它是如何进行一系列的鉴权和认证呢,下面让我们走进源码,从源码的角度来从头走一遍spring security的工作流程。
二.spring security核心结构
当一个外部请求进入到我们应用中的时候,首先会通过我们的应用过滤器链ApplicationFilterChain,我们将遍历该过滤器链中每一个Filter进行对应的处理,下面我们来看下ApplicationFiterChain一般情况下有哪些Filter
**//ApplicationFilterChain遍历内部Fiter进行doFilter()处理**private void internalDoFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException {
if (this.pos < this.n) {
ApplicationFilterConfig filterConfig = this.filters[this.pos++];
try {
Filter filter = filterConfig.getFilter();
if (request.isAsyncSupported() && "false".equalsIgnoreCase(filterConfig.getFilterDef().getAsyncSupported())) {
request.setAttribute("org.apache.catalina.ASYNC\_SUPPORTED", Boolean.FALSE);
}
if (Globals.IS\_SECURITY\_ENABLED) {
Principal principal = ((HttpServletRequest)request).getUserPrincipal();
Object[] args = new Object[]{request, response, this};
SecurityUtil.doAsPrivilege("doFilter", filter, classType, args, principal);
} else {
filter.doFilter(request, response, this);
}
从上面的图中我们可以看到,chain在一般情况下中主要存在着这么几个filter,其中有我们比较熟悉的characterEncodeingFilter字符编码的过滤器等等,以及我们本次内容的主角:springSecurityFiterChain spring security的过滤器链,可以说这就是spring security的核心所在,springSecurityFiterChain虽然为filter,但他在这里实际扮演的是一个filterChain的角色,从他的的BeanName也可以看出,那我们接下来进入springSecurityFiterChain.doFilter()方法中,看看它内部又有哪些filter,以及内部的逻辑是怎样的
可以看到springSecurityFiterChain其实是个代理bean,它的doFilter()中实际用的delegate.doFilter(),delegate是个FilterChainProxy,下面来看下FiterChainProxy的内部实现。
**FilterChainProxy.doFilter()方法内部逻辑** @Override
public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException { //如果当前游标==additionalFilters的长度,即已经遍历完该列表内的Filter,则结束FilterChainProxy.doFilter()
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;
}
this.currentPosition++; //获取列表中下一个Filter
Filter nextFilter = this.additionalFilters.get(this.currentPosition - 1);
if (logger.isTraceEnabled()) {
logger.trace(LogMessage.format("Invoking %s (%d/%d)", nextFilter.getClass().getSimpleName(),
this.currentPosition, this.size));
} //执行下一个Filter的doFilter()方法
nextFilter.doFilter(request, response, this);
}
}
我们看到FilterChainProxy中维护了一个Filter列表 additionalFilters,doFilter()中会顺序遍历这个列表,执行每一个Filter的doFilters,那这个列表中具体有哪些Filter呢,让我们来看一下
可以看到该列表中一共有13个spring security内置实现的Filter,系列文章中我们也主要来看SecurityContextPersistenceFilter security上下文持久化的过滤器,主要用来将认证过后的Authentication从session中提取注入本地线程变量中,以及UsernamePasswordAuthenticationFilter,用户密码认证过滤器,主要用来处理通过指定的登录的POST方式的请求url来进行认证…如果我们的项目中实现了JWT+Spring security的话,一般我们的我们会将自定义实现的JWT过滤器也加入到这条执行链中,并且执行位置放到UserNamePasswordAuthenticationFilter之前。
那么Spring security的大体工作流程就如下图: