Spring Security认证流程源码分析

一、通用用户权限模型 

 一般是5个表  用户表 角色表  权限表  用户角色关系表   角色权限对应表

 

项目里有很多功能,某些功能会与权限绑定,这部分功能只允许某一部分角色使用,用户可以获得多个角色,达到对不同业务功能的访问

 

spring security和apache shiro是两种比较常用的权限管理框架。boss后台的项目用到了spring security。

二、spring security简介

spring security提供认证和授权管理   它是一个强大的,高度自定义的认证和访问控制框架

三、spring security认证过程源码分析:

对于这个框架   核心的内容就是认证和授权  

认证的流程:

以登录校验为例:

 

首先用户登录了之后,登录的请求被UsernamePasswordAuthenticationFilter的doFilter方法拦截,该拦截器继承自AbstractAuthenticationProcessingFilter类

在UsernamePasswordAuthenticationFilter类中,attemptAuthentication方法

请求到了这里,接下来应该由某些具体的AuthenticationnManager去做下一步工作,这里的AuthenticationManager是一个接口

这个方法里传入的参数是  UsernamePasswordAuthenticationToken

核心验证器:

AuthenticationManager

提供了一个认证的入口,传一个Authentication类的对象作为参数

 

 

ProviderManager

这个类是AuthenticationManager的实现类,提供了基本的认证逻辑和方法,它包含了一个List<AuthenticationProvider>对象 AuthenticationProvider有很多默认实现的实现类

如果这些类不能满足需求,可以实现该接口扩展满足自己需求的认证提供方式

 

 

ProviderManager类中的认证逻辑:

1.获取参数中的认证类型,然后获取所有的Providers,遍历这些认证提供者,执行他们的验证方法

    (1)如果该provider不支持认证类型,继续遍历

    (2)如果支持,执行该provider的authticate方法进行验证

    (3)如果验证通过,将返回的Authentication对象封装成AuthenticationToken

2.如果没有任何一个provider认证成功,尝试用父类的AuthenticationManager的认证方法进行验证

3.然后擦除密码等敏感信息

 

到这里我们知道   该请求的认证类型是UsernamePasswordAuthenticationToken,这个类继承了AbstractAuthenticationToken类,AbstractAuthenticationToken这个类实现了Authentication接口

 

接下来应该寻找符合条件的Provider进行处理,这个Provider是DaoAuthenticationProvider  这个类继承了AbstractUserDetailsAuthenticationProvider,这个类实现了AuthenticationProvider接口。

 

 


AuthenticationProvider

 

AuthenticationProvider的support方法:

以AbstractUserDetailsAuthenticationProvider为例

这是一个native方法,意思是前者是后者的父类或者父接口,所以前面support判断的逻辑是:

如果参数里Authentication是当前遍历的provider的实现类,则表示参数里的认证类型可以被当前provider的验证逻辑验证

 

provider通过AuthenticationProvider扩展出很多认证的方式,AuthenticationProvider本身也是一个接口,从类图中可以看到

以AbstractUserDetailsAuthenticationProvider和它的子类DaoAuthennticationProvider为例,DaoAuthenticationProvider是spring security中的一个核心Provider,提供了所有数据库的基本方法和入口。

 


DaoAuthenticationProvider

 

DaoAuthenticationProvider主要做了两件事:

1.可以直接返回BCryptPasswordEnncoder,

或者自己去实现这个接口,

分别是加密算法和匹配规则

 

2.实现了AbstractUserDetailsAuthenticationProvider的两个抽象方法:

retrieveUser:

additionalAuthenticationChecks:

这里调用了passwordEncoder中的匹配方法,进行密码的校验

 


AbstractUserDetailsAuthenticationProvider

 

那这个方法在哪里调用的呢?在AbstractUserDetailsAuthenticationProvider类中,接着上面的,请求从filter中到了AuthenticationProvider中,然后到了AbstractUserDetailsAuthenticationProvider的authenticate方法中,这个方法的处理逻辑如下:

 

处理逻辑:

1.先执行了retrieveUser方法,获取了用户信息

2.对用户信息进行验证

    preAuthenticationChecks.check()   判断该用户是否锁定,过期,冻结User接口

    additionnAuthenticationChecks.check()  子类实现的方法  DaoAuthenticationProvider的matches方法,使用默认或者自定义的验证算法验证密码

    postAuthenticationChecks.check() 判断密码是否过期

3.验证通过之后,再将验证的信息封装成UsernamePasswordAuthenticationToken返回,该对象封装了用户信息以及相应的权限信息。如上图

 


AbstractAuthenticationProcessingFilter#doFilter

验证成功之后,请求会被默认转发回SimpleUrlAuthenticationSuccessHadler中,下图是AbstractAuthenticationProcessingFilter中的doFilter方法,进入验证的入口是attemptAuthenticationn方法,执行结束后,返回authResult,以下异常判断都没有出现并且不再有后续的filter之后,执行successfulAuthentication方法,

 

 

 

 

然后调用相应的successHandler执行onAuthenticationSuccess方法:

这里以SavedRequestAwareAuthenticationnSuccessHandler为例

它的逻辑是: 首先从缓存中获取请求信息,如果为空调用父类的onAuthenticationSuccess方法

不为空获取目标URL以及相关参数。然后获取重定向的url,进行重定向。

 

 

这里有个记住我的逻辑,当用户认证成功之后,调用rememberMeServices的loginSuccess方法,跳入到具体的rememberMeService实现类中,

以TokenBaseRememberMeServices为例,该类继承自抽象类AbstractRememberMeServices,该抽象类实现了RememberMeService接口。

AbstractRememberMeSerivice类中有loginSuccess方法,该方法是抽象方法,例如TokenBaseRememberMeSerivices实现

该方法配置了过期时间,token有效时间,然后将相关信息写入Cookie


RememberMeAuthenticationnFilter

下次登录后,会由RememberMeAuthenticationnFilter进行拦截,读取Cookie中的Token,与数据库表中的信息匹配是否使用记住我功能。

 

如果rememberMeAuth不为空,继续由Authentication进行认证。

 

 

配合JWT可以实现单点登录。

 

 

 

 

 

参考:

https://blog.csdn.net/ltx0720/article/details/90299410

https://blog.csdn.net/dandandeshangni/article/details/78959131

https://blog.csdn.net/lvhao2813/article/details/81974242

https://blog.csdn.net/dandandeshangni/article/details/79090952

https://www.cnblogs.com/cjsblog/p/9152455.html

https://blog.csdn.net/XlxfyzsFdblj/article/details/82084183

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值