Shiro登录校验以及授权流程的源码分析

原文:https://www.jianshu.com/p/6abc22ec3cb8
源码分析(加入了自己的一些想法,黄底)

①我们在登录操作时打好断点,debug运行

我这边配置是继承FormAuthenticationFilter进行web拦截,然后通过阅读博客我学习到了,该过滤器因着继承其他类的原因,会默认进行执行subject.login();
参考:shiro之深度解析FormAuthenticationFilter
https://www.cnblogs.com/dengpengbo/p/10794346.html

②我们进入到subject主体的实现类中,注意标记部分,subject将登录操作委托给了securitymanager,参数除了页面传入的token以外还有subject主体
在这里插入图片描述
③进入到securitymanager实现类中,开始执行认证方法
我这边的配置是DefaultWebSecurityManager继承于DefaultSecurityManager
在这里插入图片描述

④点进去看一下,我们发现securitymanager将认证任务委托给了认证器,由认证器执行认证方法
在这里插入图片描述
⑤我们进入到认证方法中
在这里插入图片描述
⑥继续执行doAuthenticate,我们发现这里面有个realm,他是啥呢?
阅读其他作者的博文:我大概知道,含该方法的类ModularRealmAuthenticator,会调用SecurityManager.realms配置中的realm
在这里插入图片描述
我们看到realms这个集合里面其实就是我们之前加载的realms.ini中的内容
在这里插入图片描述
作者是为了简便直接采用ini配置了,我这边是通过继承AuthorizingRealm(继承于AuthenticatingRealm)自定义的realm,实现了doGetAuthenticationInfo和doGetAuthorizationInfo方法

⑦因为我们只有一个realm,所以进入了true条件中,这时我们刚才标记出的AuthenticationInfo出现了,看看他是啥
在这里插入图片描述
点进去看看
在自定义realm父类的父类AuthenticatingRealm的getAuthenticationInfo方法,其中就调用了被我们实现的需自定义方法doGetAuthenticationInfo
由此获取AutherticationInfo,后续进行校验
在这里插入图片描述
看不懂,继续进去看看,我们看到他先把我们的token包装成了 UsernamePasswordToken的形式 然后执行了getuser()参数是我们页面传进来的token的name
在这里插入图片描述
⑧我们看一下里面是什么,是通过页面传入的那个用户名,去我们刚才realm里面的user列表去查找有没有这个用户 如果找到了,将realm中该用户信息返回上一层
在这里插入图片描述
密码验证就很简单了,重点就是这个判断
我这边因为自定义realm没有配置credentialsMatch,所以根据源码直接跳过
关于credentialsMatch
参考:Shiro之CredentialsMatcher详解
https://blog.csdn.net/dh554112075/article/details/90760318
在这里插入图片描述
其实就是把我们刚才取得的那个realm中的张三的密码和我们页面传入的密码比较
在这里插入图片描述
然后就是依次进行返回AutherticationInfo,直到
在这里插入图片描述
这个createSubject方法对subject进行设置,尤其是这个setAuthentivated方法
在这里插入图片描述
这时候我们通过controller来进行判断是否验证subject.isAuthenticated();
至此就完成整个登录验证(认证)了。

然后是授权(权限管理):
JSP授权(页面上根据权限设置菜单显示与否)
引入shiro的标签库,在Jsp页面头部添加:

<%@ taglib uri="http://shiro.apache.org/tags" prefix="shiro" %>

常用:
拥有权限资源abc

<shiro:hasPermission name="abc">
	该权限下可用内容或操作
</shiro:hasPermission>

源码:
在这里插入图片描述
该类内就只是实现父类的方法(内容是调用另一个父类方法),判断权限后决定是否显示shiro标签内的内容
在这里插入图片描述
调用的父类方法
在这里插入图片描述
该父类方法通过继承父类方法,获取subject
在这里插入图片描述
然后就是了解subject.isPermitted(String)如何执行:
(其他方法配置实现授权应该也是回到调用该方法)
漫长的查找过程…
subject.isPermitted(String)->delegatingSubject.isPermitted(String)->
securityManager.isPermitted(PrincipalCollection, string)
这里的PrincipalCollection很重要,这是上面登录时AutherticationInfo所创建、保存的,并且在创建subject时成为其属性对象

  1. SimpleAuthenticationInfo的PrincipalCollection属性,和构造方法
    在这里插入图片描述
    在这里插入图片描述

  2. 登录认证时,在doGetAuthenticationInfo中被使用
    在这里插入图片描述
    Principal类只是个自定义的类保存用户id和用户名信息的

  3. 被保存在subject里(DefaultSecurityManager.login()->DefaultSecurityManager.createSubject)
    在这里插入图片描述

->defaultSecurityManager无该方法,但其父类的父类的AuthorizingSecurityManager有该方法->modularRealmAuthorizer.isPermitted(PrincipalCollection, string)
在这里插入图片描述
要保证realm类型以及有该权限才授权
最后决定权到了realm的手上,我这边自定义的realm继承AuthorizingRealm,其下方法:
在这里插入图片描述
getAuthorizationInfo方法内调用重写的doget方法
在这里插入图片描述
从PrincipalCollection中取出存放用户名id和用户名的自定义类Principal,然后根据用户id查权限,查角色,两个参数都是字符串集合
在这里插入图片描述

permission接口实现implies方法的两个类WildcardPermission 和 AllPermission(不进行判断全部允许)
在这里插入图片描述
至此就是理解(可能也不必要吧,结果就是是否匹配)这个方法
Set集合的containAll方法:本集合(本用户所有权限)是否含有作为参数的集合(标签的权限)的所有内容
等价于
两集合关系是否包含

后记:不足之处也请指教,因为想去了解这些工具或者框架的原理,所以也在找博客去阅读,大部分内容都是借鉴他人的成果,然后加以理解,整理后再在博客上留下记录。
对于这些工具或框架个人觉得不明白其中流程就比较烦,摸不着头脑,看着是这么配置但它怎么工作却不知道(可能这是作者的初衷吧),更别提会用不会用了,所以学习进度很慢,一开始想学shiro但是不太懂,看了各种各样的配置还是摸不清,直到最近有个可以用的例子,然后就像再学学弄明白。
自己还差很多,还得学习。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值