Shiro ,绕不过的 Realm

简介: 上篇文章和小伙伴们仔细聊了聊 Shiro 中的登录操作,官方的 demo 中对登录操作也有很多英文注释,相信大家都能理解,但是对于整个登录的过程,可能小伙伴们还有一些疑惑,那么本篇文章我将和小伙伴们分享一下 Shiro 中的登录流程,顺便介绍一个重要的类--Realm。

登录流程是什么样的

首先我们来看 shiro 官方文档中这样一张登录流程图:


42.jpg

参照此图,我们的登录一共要经过如下几个步骤:

  1. 应用程序代码调用 Subject.login 方法,传递创建好的包含终端用户的 Principals(身份)和 Credentials(凭证)的 AuthenticationToken 实例(即上文例子中的 UsernamePasswordToken)。
  2. Subject 实例,通常是 DelegatingSubject(或子类)委托应用程序的 SecurityManager 通过调用 securityManager.login(token) 开始真正的验证工作(在 DelegatingSubject 类的 login 方法中打断点即可看到)。
  3. SubjectManager 作为一个基本的“保护伞”的组成部分,接收 token 以及简单地委托给内部的 Authenticator 实例通过调用 authenticator.authenticate(token)。这通常是一个 ModularRealmAuthenticator 实例,支持在身份验证中协调一个或多个 Realm 实例。ModularRealmAuthenticator 本质上为 Apache Shiro 提供了 PAM-style 范式(其中在 PAM 术语中每个 Realm 都是一个'module')。
  4. 如果应用程序中配置了一个以上的 Realm,ModularRealmAuthenticator 实例将利用配置好的 AuthenticationStrategy 来启动 Multi-Realm 认证尝试。在 Realms 被身份验证调用之前,期间和以后,AuthenticationStrategy 被调用使其能够对每个 Realm 的结果作出反应。如果只有一个单一的 Realm  被配置,它将被直接调用,因为没有必要为一个单一 Realm 的应用使用 AuthenticationStrategy。
  5. 每个配置的 Realm 用来帮助看它是否支持提交的 AuthenticationToken。如果支持,那么支持 Realm 的 getAuthenticationInfo 方法将会伴随着提交的 token 被调用。

OK,通过上面的介绍,相信小伙伴们对整个登录流程都有一定的理解了,小伙伴可以通过打断点来验证我们上文所说的五个步骤。那么在上面的五个步骤中,小伙伴们看到了有一个 Realm 承担了很重要的一部分工作,那么这个 Realm 到底是个什么东西,接下来我们就来仔细看一看。

什么是 Realm

根据 Realm 文档上的解释,Realms 担当 Shiro 和你的应用程序的安全数据之间的“桥梁”或“连接器”。当它实际上与安全相关的数据如用来执行身份验证(登录)及授权(访问控制)的用户帐户交互时,Shiro 从一个或多个为应用程序配置的 Realm 中寻找许多这样的东西。在这个意义上说,Realm  本质上是一个特定安全的 DAO:它封装了数据源的连接详细信息,使 Shiro 所需的相关的数据可用。当配置 Shiro 时,你必须指定至少一个 Realm 用来进行身份验证和/或授权。SecurityManager 可能配置多个 Realms,但至少有一个是必须的。Shiro 提供了立即可用的 Realms 来连接一些安全数据源(即目录),如 LDAP,关系数据库(JDBC),文本配置源,像 INI 及属性文件,以及更多。你可以插入你自己的 Realm 实现来代表自定义的数据源,如果默认地 Realm 不符合你的需求。

看了上面这一段解释,可能还有小伙伴云里雾里,那么接下来我们来通过一个简单的案例来看看 Realm 到底扮演了一个什么样的作用,注意,本文的案例在上文案例的基础上完成。首先自定义一个 MyRealm,内容如下:

publicclass MyRealm implements Realm {
    public String getName() {
        return"MyRealm";
    }
    public boolean supports(AuthenticationToken token) {
        return token instanceof UsernamePasswordToken;
    }
    public AuthenticationInfo getAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        String password = new String(((char[]) token.getCredentials()));
        String username = token.getPrincipal().toString();
        if (!"sang".equals(username)) {
            thrownew UnknownAccountException("用户不存在");
        }
        if (!"123".equals(password)) {
            thrownew IncorrectCredentialsException("密码不正确");
        }
        returnnew SimpleAuthenticationInfo(username, password, getName());
    }
}

自定义 Realm 实现 Realm 接口,该接口中有三个方法,第一个 getName 方法用来获取当前 Realm 的名字,第二个 supports 方法用来判断这个 realm 所支持的 token,这里我假设值只支持 UsernamePasswordToken 类型的 token,第三个 getAuthenticationInfo 方法则进行了登陆逻辑判断,从 token 中取出用户的用户名密码等,进行判断,当然,我这里省略掉了数据库操作,当登录验证出现问题时,抛异常即可,这里抛出的异常,将在执行登录那里捕获到(注意,由于我这里定义的 MyRealm 是实现了 Realm 接口,所以这里的用户名和密码都需要我手动判断是否正确,后面的文章我会介绍其他写法)。

OK,创建好了 MyRealm 之后还不够,我们还需要做一个简单配置,让 MyRealm 生效,将 shiro.ini 文件中的所有东西都注释掉,添加如下两行:

MyRealm= org.sang.MyRealm
securityManager.realms=$MyRealm

第一行表示定义了一个 realm ,第二行将这个定义好的交给 securityManger,这里实际上会调用到 RealmSecurityManager 类的 setRealms 方法。OK,做好这些之后,小伙伴们可以在 MyRealm 类中的一些关键节点打上断点,再次执行 main 方法,看看整个的登录流程。

好了,本文我们介绍了一个简单的 realm 操作,更多 realm 操作,我们下篇文章继续来谈。

本文案例下载地址:https://github.com/lenve/shiroSamples/archive/v3.zip

参考资料:

  1. 维基百科-Apache Shiro
  2. Shiro 参考手册

欢迎加入我们的知识星球,一起成长,交流经验。加入方式,长按下方二维码噢

最后,我想重复一句话:选择和一群优秀的人一起成长,你成长的速度绝对会不一样!

相关文章
|
12月前
|
SQL 安全 测试技术
05 Shrio Realm
05 Shrio Realm
36 0
|
安全 Java 数据库连接
Shiro 中的 Realm
Shiro 中的 Realm
104 0
|
Java API 数据库
Shiro学习之Shiro基本使用(1)
Shiro学习之Shiro基本使用(1)
84 0
|
Java 数据库 数据安全/隐私保护
Shiro学习之Shiro基本使用(2)
Shiro学习之Shiro基本使用(2)
53 0
|
存储 缓存 安全
2021年你还不会Shiro?----1.Shiro的架构
涉及到多用户登录的系统时都要对用户进行权限管理,权限管理属于系统安全的范畴,权限管理主要是为了实现“对用户访问系统的控制”,根据安全规则去控制用户可以访问的资源。
133 0
2021年你还不会Shiro?----1.Shiro的架构
|
缓存 安全 Apache
2021年你还不会Shiro?----3.分析身份认证源码实现自定义Realm
我们已经知道无论我们是认证还是授权,数据的获取都是来源于Realm,Realm就相当于我们的datasource,在上一篇中我们使用的是用IniRealm来加载我们的配置文件shiro.ini,同时我们也说了ini只是临时解决方案,在实际的开发中是不可能把用户信息和权限信息放在ini文件中的,都是来源于数据库,那么系统提供的IniRealm就不能满足我们的需要了,我们就需要自定义Realm来实现真正的场景,事实上ini文件也只是apache为我们提供学习使用的策略,下面我们就来看下怎么自己定义一个Realm。
107 0
2021年你还不会Shiro?----3.分析身份认证源码实现自定义Realm
|
缓存 前端开发 程序员
Shiro实现多realm方案
前后端分离的背景下,在认证的实现中主要是两方面的内容,一个是用户登录获取到token,二是从请求头中拿到token并检验token的有效性和设置缓存。
Shiro实现多realm方案
|
安全
shiro多realm抛出异常问题
使用Shiro作为安全框架时,为了方便我们可以把异常提出为公共模块,当使用多Realm时,需要特殊处理下,不然,异常时只会抛出一种。最近写项目时,就遇到了该问题,本身项目有一个登录系统,需要多加一个OAuth2的单点登录,服务端已经OK,需要在项目中对接一下该服务端;特此记录下
350 1
|
缓存 Java 数据库
Shiro - 基础篇(上)
Shiro - 基础篇(上)
145 0
Shiro - 基础篇(上)
|
SQL druid 数据库
再谈 Shiro 中的 Realm
上篇文章和小伙伴们聊了 realm 的简单操作,本文我们来继续深入这个话题。
再谈 Shiro 中的 Realm