Spring Security源码解析一:UsernamePasswordAuthenticationFilter之登录流程

本文是Spring Security源码解析的第一部分,主要探讨了UsernamePasswordAuthenticationFilter的登录认证流程。当POST请求发送到/login时,Spring Security会通过一系列过滤器进行处理,包括检查请求、尝试认证、数据库用户信息校验等步骤。
摘要由CSDN通过智能技术生成

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的大体工作流程就如下图:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值