SpringBoot整合SpringSecurity(二)认证流程

上一篇文章我们做了一个简单的入门程序,我们这一篇就来简单的跟踪源码,来分析一下其中的原理,顺便了解了整个流程后更方便我们扩展去做不同的登陆。

认证流程

我们就拿上一篇的登陆来做一个分析。

用户在页面上输入 用户名密码后访问响应的登陆方法 会进入到 UsernamePasswordAuthenticationFilter
然后会进入到attemptAuthentication 方法中。在这个方法里呢我们拿到请求中的用户名 和密码 并且构建了一个 UsernamePasswordAuthenticationToken 我们点进去看一下构建的什么

原来在构造方法里 setAuthenticated(false) 就代码这个 AuthenticationToken 没有进行认证。

最后返回值 返回给 AuthenticationManager 进行验证,好我们接着向下走

随后我们进入到了 ProviderManager 里 顾名思义就是各种 Provider 的管理器。

此时呢 先拿到我们构建未认证的 UsernamePasswordAuthenticationToken 的class 与上下文中的所有 AuthenticationProvider 进行对比,如果通过


会给相对应的 AuthenticationProvider 进行 验证我们继续向下走

此时我们进入到了 AbstractUserDetailsAuthenticationProvider

这里说明一下 AbstractUserDetailsAuthenticationProviderDaoAuthenticationProvider 的抽象类

这里呢会调用

自身的 retrieveUser 方法进行用户的查找,我们进去看一下,果然 这里调用了上下文中的UserDetailsService 也就是我们自定义的那个 进行用户的查找


然后接着向下走


用户找到了 , 然后我们从前台输入的 认证信息也带过来了,干嘛呢 ?进行对比啊,这里security进行 几层对比

如果全部通过 则会走Provider 自己的 createSuccessAuthentication 方法 我们进去看一看

哦 原来这里要在进行密码的比对,方法名为Success 只是用户找到了而已0.0,密码验证通过了才会到真正的方法里然后返回 Authentication

不难看出这里重新构建了一个 UsernamePasswordAuthenticationToken 把用户设置为已经认证状态

然后这个流程算是走完了 接着回到我们了 ProviderManager

此时我们的方法已经走完了 这时候我们会进入到 AbstractAuthenticationProcessingFilter 顾名思义就是所有认证处理器的过滤器 的 doFilter() 方法里


然后这个过滤器就走完了


走到successfulAuthentication 或者 unsuccessfulAuthentication 就证明我们走完了整个认证流程。

后续整个方法会吧认证信息放入 SecurityContextHolder.getContext() 其实就是在这里将认证信息放入 Session 中。

查看 SecurityContext 源码,发现内部就是对 Authentication 的封装,提供了 equals、hashcode、toString等方法,而SecurityContextHolder 可以理解为线程中的 ThreadLocal

我们知道一个 HTTP 请求和响应都是在一个线程中执行,因此在整个处理的任何一个方法中都可以通过 SecurityContextHolder.getContext()来取得存放进去的认证信息。

结论

上面那些我相信大家都没怎么看,我这里呢就画图来总结一下整个认证流程

差不多就是这样一个流程

  1. 进入 UsernamePasswordAuthenticationFilter 然后构建一个没有认证的 UsernamePasswordAuthenticationToken
  2. 随后交给 AuthenticationManager 进行验证,
  3. AuthenticationManager 找到对应的 AuthenticationProvider进行认证
  4. AuthenticationProvider找到上下文中的UserDetailsService 中寻找用户然后对比
  5. 验证成功返回 Authentication 放入 SecurityContextHolder

从 session 中对认证信息的处理由 SecurityContextPersistenceFilter 来处理,它位于 Spring Security 过滤器链的最前面,它的主要作用是:

  • 当请求时,检查 Session 中是否存在 SecurityContext,如果有将其放入到线程中。
  • 当响应时,检查线程中是否存在 SecurityContext,如果有将其放入到 Session 中。



    Security的过滤链我以后的帖子说权限验证的时候中会详细说明

我们了解这样一个登陆的流程后 要定制一个自己的登陆过滤器加入到SpringSecurity的过滤连中。下一篇帖子在讲。

本博文是基于springboot2.x 和security 5 如果有什么不对的请在下方留言。