Springsecurity登录的源码追踪。

流程图:如下。
在这里插入图片描述

1.密码登录请求给UsernamePasswordAuthenticationFilter,此过滤器将用户名和密码拿出来组装成UsernamePsswordAuthenticationToken(未认证)对象。

在这里插入图片描述
在这里插入图片描述
查看继承图可以看到它是Authentication接口的一个实现,Authentication里面封装了用户的认证信息
在这里插入图片描述
这时调用的构造函数,将用户名密码设为本地变量principalcredentialssuper调用父类的构造函数,因为此时并不知道用户有什么权限,所以为null在这里插入图片描述
创建好UsernamePasswordAuthenticationToken对象之后,同时将请求信息也封装进去进入到getAuthenticationManager().authenticate(authRequest);
getAuthenticationManager()方法返回一个AuthenticationManager接口的实现类,跟进去authenticate()方法
在这里插入图片描述
这是AuthenticationManager的一个实现类ProviderManager
在这里插入图片描述
在这个方法中,循环找出一个AuthenticationProvider的实现类,来调用实现类的authenticate方法来进行认证,不同的登陆方式所需要的AuthenticationProvider的实现类不同,所以这里要循环找出适合当前登陆方式的provider,这里使用的是DaoAuthenticationProvider
这里需要注意的是,如果是选用的短信认证登录的话,这里选择的是我们自己写的SmsCodeAuthenticationProvider
在这里插入图片描述
进入authenticate方法,首先来到的是DaoAuthenticationProvider的抽象父类
在这里插入图片描述
进入retrieveUser()方法:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里会拿到UserDetailsService的具体实现类,执行loadUserByUsername()方
查看this.getUserDetailsService(),可以看到返回的就是我们自己写的实现类:UserLoginService,然后执行loadUserByUsername()方法返回User对象(实现了UserDetails接口的)。通过上面的方法调用下面自己写的UserLoginService,来获取用户信息。
在这里插入图片描述
在这里插入图片描述
然后通过下面的方法去判定用户是否锁定,是否可用,是否过期。
在这里插入图片描述
在这里插入图片描述
通过下面的方法判断rawPassword(表单输入的密码)和存入数据库中加密之后的密码(encodePassword)进行判定。
在这里插入图片描述
在这里插入图片描述
然后先经过下图的代码段1处后,在到代码段2处。经过这次调用的是UsernamePasswordAuthenticationToken三个参数的构造器,因为此时已经拿到了认证信息authoritiessuper.setAuthenticated(true)已经认证
这时AbstractUserDetailsAuthenticationProvider的authenticate方法,执行
createSuccessAuthentication返回一个经过认证的Authentication对象。由下图的3处可以看到已经认证成功
一步一步返回到UsernamePasswordAuthenticationFilter
然后会经过一个AbstractAuthenticationProcessingFilter,在这个抽象类中执行doFilter()方法。

在这里插入图片描述
成功就执行成功的处理器,失败则执行失败的处理器。
在这里插入图片描述
如下图。到我们自己写的成功处理器。执行到这里,已经登陆成功,相应的登陆信息也返回给登陆请求。
在这里插入图片描述
下面看看不同的请求是如何拿到认证信息的(认证结果在不同的请求之间共享):
在这里插入图片描述
AbstractAuthenticationProcessingFilter中可以看到,在执行成功处理器之前,会执行SecurityContextHolder.getContext().setAuthentication(authResult);这个authResult就是包含了已登陆的用户授权信息的Authentication对象
SecurityContextHolder:Associates a given SecurityContext with the current execution thread.(将给定的SecurityContext与当前执行线程关联。)
SecurityContext:安全上下文,即存储认证授权的相关信息,实际上就是存储"当前用户"账号信息和相关权限。这个接口只有两个方法,获取和设置Authentication对象的getter、setter方法。

SecurityContextHolder使用了ThreadLocal机制来保存每个使用者的安全上下文。这意味着,只要针对某个使用者的逻辑执行都是在同一个线程中进行,即使不在各个方法之间以参数的形式传递其安全上下文,各个方法也能通过SecurityContextHolder工具获取到该安全上下文。SecurityContextPersistenceFilter是拦截链中的第一个拦截器,当一次请求结束时,这个过滤器会看当前线程上是否保存有SecurityContext,如果有则会被存到session中,sessionId被设置到cookie中,登陆之后的其他请求到来时,通过sessionId可以拿到session,把SecurityContext拿出来通过SecurityContextHolder放到当前线程中,从而在整个请求的流程中都可以拿到用户信息。

SecurityContextHolder获取用户信息:

@RestController
public class SecurityContextHolderController {
    @GetMapping("getUserMsg")
    public Object getCurrentUser(){
        return SecurityContextHolder.getContext().getAuthentication();
    }
}

登陆之后访问接口:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值