述
前面的文章中首先分析了认证流程的源码,然后我们又实现了自己的登录流程以及一些自定义的处理,下面再来梳理一下这些认证的流程
认证
这里我们之前就已经分析过认证流程了,这里再坐下补充以及回顾,先看下图:
首先是进到了 UsernamePasswordAuthenticationFilter
, 然后这个里面生成了一个没有经过认证的 Authentication
对象, 然后是调用 AuthenticationManager
找到处理当前登录请求的 AuthenticationProvider
, 然后通过 UserDetailsService
做用户的验证(密码等), 然后组装返回一个已认证的 Authentication
对象
这部分的源码之前已经说过了,这里就不再看了
认证成功/失败处理
在 UsernamePasswordAuthenticationFilter
返回 Authentication
对象之后,会进入到 AbstractAuthenticationProcessingFilter
这个 filter 里面, 看一下源码
然后这里主要是判断是否登录成功, 在catch块里面都是调用的认证失败的处理, 然后最后是调用的认证成功的处理
分别看一下这两个方法的源码
这里每个方法的最后一行,就是去调用我们的自定义的成功/失败的处理
认证结果如何在多个请求之间共享
认证完成之后,那认证结果是如何在多个请求中共享的,一般都是在登录成功之后放到session里面,我们详细的看一下这个认证成功后调用的方法
SecurityContext
可以看到这里把认证结果放到了 SecurityContext
里面,先来看下面这个图:
认证成功之后,先把认证结果放到了一个 SecurityContext
里面,这个是个接口,实际的实现类是 SecurityContextImpl
,看一下源码
里面包装了Authentication
主要就是重写了 equals
还有 hashCode
, 保证Authentication
的唯一性
SecurityContextHolder
然后,是把这个放到了一个 SecurityContextHolder
里面,这个类实际上对 ThreadLocal
的一个封装,可以在不同方法之间进行通信,我们可以简单理解为线程级别的一个全局变量.因此可以在同一个线程中的不同方法中获取到认证信息
SecurityContextPersistenceFilter
最后一步是经过 SecurityContextPersistenceFilter
这个过滤器, 这个也是 security 过滤器链中的一个,位置如下
这个过滤器的作用就是 当一个请求来的时候,它会将session中的值传入到该线程中,当请求返回的时候,它会判断该请求线程是否有 SecurityContext
, 如果有它会将其放入到session中,因此保证了请求结果可以在不同的请求之间共享
获取认证信息
最后来看一下如何获取用户的认证信息,这个有以下几种方式去拿
第一种
新建接口,代码如下:1
2
3
4@GetMapping("/me")
public Object me(){
return SecurityContextHolder.getContext().getAuthentication();
}
第二种
1 | @GetMapping("/me") |
第三种
1 | @GetMapping("/me") |
效果
第一种和第二种方式返回的结果都是一样的,都是返回的 Authentication
对象,如下:
第三种方式是只返回了 UserDetails
对象,如下:
总结
本文主要是介绍了认证结果共享的原理,就是在认证成功之后放到了一个 SecurityContext
里面,最后通过最外层的过滤器 SecurityContextPersistenceFilter
放到session里面,从而实现认证结果共享
最后就是几种通过接口获取认证后的结果的方法
代码已经上传github,传送门