Apache shiro源码解读——Realm调用过程(从SecurityUtils.getSubject().login(token)开始)

本篇博文从SecurityUtils.getSubject().login(token)开始分析,详细解读了shiro如何通过AuthenticationToken找到Realm类完成具体校验逻辑。旨在通过源码分析让同学们轻松发现扩展shiro的的方式,可根据自己的业务需求快速完成自定义AuthenticationToken和自定义Realm构建,了解shiro的部分运行原理。同时对自己学习和运用shiro的经历做个记录和总结。

shiro是啥

根据官网介绍,“Apache Shiro™ is a powerful and easy-to-use Java security framework that performs authentication, authorization, cryptography, and session management. With Shiro’s easy-to-understand API, you can quickly and easily secure any application – from the smallest mobile applications to the largest web and enterprise applications.”
shiro是一个功能强大,便于使用的java安全框架,可以提供授权、认证、加密和session管理等功能,通过shiro简易的API接口可以简单快速为web应用构建标准化的安全认证体系架构。

shiro中的三个核心模型抽象

shiro中的三个核心概念是:SecurityManager、Subject和Realm。其中SecurityManager是“容器”,所有shiro操作都由SecurityManager管理,subject是主体,是“用户”的抽象。保存有关于主体的详细信息。Realm是“域”,在Realm中进行权限等的操作。
可参考博文shiro官网
Token对象保存subject(主体)的身份校验信息,例如:用户名、密码、token字符串等,并提供了principal(例如:用户名,token字符串等)和Credentials(例如:密码)两种抽象类型,Realm相关实现类中通过Token信息完成对subject的安全校验。shiro就是通过token找到对应的realm的。

authentication 认证(login)
authorization 授权(access control)

从SecurityUtils.getSubject().login(token)开始一段源码解读

在web应用中,初始化shiro的相关Bean之后,往往会在filter中进行接口的权限校验。最常使用的是SecurityUtils.getSubject().login(token),进行主体(subject)的合法性判断。shiro会根据Token类型对应的Realm,执行详细的判断逻辑。理解这一过程有利于我们在shiro的基础上进行扩展,定制化满足自身业务需求的realm、filter和AuthenticationToken。

从subject的具体实现类DelegatingSubject的login方法开始,看看shiro是怎样一步一步找到对应的realm的:

![在这里插入图片描述](https://img-blog.csdnimg.cn/20190730201507271.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L25ld0NoZW5n,size_16,color_FFFFFF,t_70
在这里插入图片描述
SecurityManager接口的相关实现类如上,我们在demo中实例化了DefaultWebSecurityManager bean作为SecurityManager的具体实现。映射到具体realm一定是在securityManager.login(this, token);中进行。我们看下DefaultWebSecurityManager类中login()这个方法:
在这里插入图片描述继续看该类authenticate()方法:
在这里插入图片描述在这里插入图片描述我们看到AnthenticatingSecurityManager类构造方法中实例化了一个ModulerRealmAuthenticator类作为Authenticator接口的实现,所以具体执行的是ModularRealmAuthenticator类的相关方法,但是查看该类并没有提供authenticate()方法。这里shiro通过ModularRealmAuthenticator的父级抽象类实现了一个简单的模板方法模式。子类重写doAuthenticate()方法由抽象类authenticate方法具体执行,看下AbstractAuthenticator具体实现:
在这里插入图片描述看下ModularRealmAuthenticator类的doAuthenticate方法,其中获得所有realm信息的list,对于单条记录执行doSingleRealmAuthentication方法,对于多条记录执行doMultiRealmAuthentication方法。
在这里插入图片描述
realm.supports(token);方法决定了token对应要执行的Realm类。可以看到Realm接口定义的support方法的唯一具体实现是在抽象类AuthenticatingRealm中。
在这里插入图片描述
getAuthenticationTokenClass()方法获的该类的authenticationTokenClass属性,查看构造方法可以看出该realm默认对应的Token类是UsernamePasswordToken。如下所示:
在这里插入图片描述
综上,如果shiro使用DefaultWebSecurityManage这个Bean,默认使用UsernamePasswordToken这个Token,使用AuthenticatingRealm这个realm。

自定义Realm的两种轻松实现方式

通过对shiro小部分源码的分析,我们发现对主体subject进行校验的具体逻辑是在realm中实现的。而完成特定主体与具体realm的对应是通过AuthenticationToken的具体实现类实现的。我们可以定义不同的Token实现类从而解决不同subject与不同realm之间的映射关系,并实现多种逻辑组合。
查看realm源码我们发现shiro提供的多种类型的权限校验抽象,支持redis缓存,jdbc,ldap等多种数据源。
在这里插入图片描述
以下提供两种方式:

方式一

在自定义Realm类中构造方法中显示的set特定的AuthenticationToken类,例如我们在自定义的Realm中这样构建:
在这里插入图片描述

方式二

继承ModularRealmAuthenticator类重写doAuthenticate方法,例如:
在这里插入图片描述

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Apache Shiro 是一个功能强大的Java安全框架,可以用来实现身份验证、授权、加密、会话管理等安全相关的功能。下面是使用 Apache Shiro 实现权限控制的一些步骤: 1. 引入 Apache Shiro 的依赖:在项目中引入 Apache Shiro 的相关依赖,包括 shiro-core 和 shiro-web。 2. 配置 Shiro:在项目中配置 Shiro 相关的配置文件,如 shiro.ini 或 shiro.xml。 3. 编写 Realm:在 Shiro 中,Realm 是用来获取安全数据(如用户、角色、权限等)的组件。需要根据具体的业务需求编写自己的 Realm 实现类,并在 Shiro 配置文件中进行配置。 4. 实现权限控制:在代码中使用 Shiro 的 Subject 对象进行权限控制,可以通过调用 Subject 的 hasRole() 和 isPermitted() 方法来判断用户是否具有某个角色或权限。 下面是一个简单的示例代码: ``` // 获取当前用户 Subject currentUser = SecurityUtils.getSubject(); // 判断用户是否有某个角色 if (currentUser.hasRole("admin")) { // 执行管理员操作 } else { // 没有管理员角色,执行普通用户操作 } // 判断用户是否有某个权限 if (currentUser.isPermitted("user:create")) { // 执行创建用户操作 } else { // 没有创建用户权限,执行其他操作 } ``` 需要注意的是,使用 Apache Shiro 实现权限控制时,需要先进行身份验证(即用户登录),才能进行权限控制。可以使用 Shiro 的 Authentication API 进行身份验证,例如: ``` UsernamePasswordToken token = new UsernamePasswordToken(username, password); try { currentUser.login(token); } catch (AuthenticationException e) { // 身份验证失败 } ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值