认证流程源码分析
之前的代码中,我们自定义了登陆路径,自定义成功和失败处理器以及自定义的用户登陆信息校验,下面我们通过简单的源码分析,来把这些串联起来
- 认证流程处理说明
- 认证结果如何在多个请求之间共享
- 获取认证用户信息
认证处理流程说明
spring-security过滤器链
关于web中过滤器 、拦截器 、监听器区别 https://blog.youkuaiyun.com/Jintao_Ma/article/details/52972482
idea断点调试:https://blog.youkuaiyun.com/deepwishly/article/details/54645022
表单过滤器认证流程如下:
UsernamePasswordAuthenticationFilter:表单用户名登陆过滤器
AuthenticationManager:管理所有的Provider,并选择适合的进行验证
AuthenticationProvider:验证提供者,可以自己写provider处理自己的业务场景逻辑
UserDetailsService:验证用户登陆信息
UserDetails:用户信息
Authentication:认证信息封装
下面我们进行登陆断点调试:
UsernamePasswordAuthenticationFilter
UsernamePasswordAuthenticationToken 它实现Authentication这个认证接口
public class ProviderManager implements AuthenticationManager, MessageSourceAware, InitializingBean
AbstractUserDetailsAuthenticationProvider
DaoAuthenticationProvider
MyUserDetailServiceImpl 确实是我们自定义的实现
AbstractUserDetailsAuthenticationProvider
登陆验证成功后 AbstractAuthenticationProcessingFilter
认证结果如何在多个请求之间共享
在已经认证成功的情况下
SecurityContext 默策略是一个 org.springframework.security.core.context.ThreadLocalSecurityContextHolderStrategy 对象,
内部使用`ThreadLocal<SecurityContext>`来存储;ThreadLocal线程的变量,同一个线程可以读取
SecurityContextPersistenceFilter会先查询session中是否已经认证了。出去的时候回将认证信息存入session。这样就解决了请求的共享的问题
获取认证用户信息
UserController,通过前面的认证信息如何在多个请求之间共享我们知道可以直接从SecurityContextHolder中获取认证信息,我们来测试下
package com.rui.tiger.auth.demo.controller;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 用户控制器
*
* @author CaiRui
* @date 2018-12-6 8:16
*/
@RestController
@RequestMapping("/user")
public class UserController {
@RequestMapping("/hello")
public String hello() {
return "Hello,World";
}
/**
*获取用户认证信息
* @return
*/
@GetMapping("authentication")
public Authentication getCurrentAuthentication(){
return SecurityContextHolder.getContext().getAuthentication();
}
/**
* 获取用户认证信息
* 同getCurrentAuthentication spring 会帮我们注入
* @param authentication
* @return
*/
@GetMapping("authentication/auto")
public Authentication getCurrentAuthentication2(Authentication authentication){
return authentication;
}
}
首先进入登陆界面,登录成功后我们再输入http://localhost:8070/user/authentication可以看到成功获取到认证信息
序列化格式看下
有时我们只想看到认证主体信息可以这样设置 使用参数注解@AuthenticationPrincipal UserDetails userDetails
获取User的信息
ok基于源码分析的 我们就先到这里,下一章我们将开发通用的验证码登陆