上一篇文章中提到了Realm,它相当于datasource数据源,SecurityManager进行安全验证时需要通过Realm获取用户权限数据,比如:如果用户身份数据在数据库,那么Realm就需要从数据库中获取用户身份信息。因此,在本文中我们将通过跟踪源码的形式来看一下Shiro中的认证和授权是如何完成的。

1、 源码跟踪

以上一篇文章的代码为例,在subject.login()进行断点调试,整体过程如下:

(1)进入DelegatingSubject的login()方法。

(2)调用DelegatingSubject的login()方法

(3)调用本类中的authenticate方法

(4)调用AbstractAuthenticator中的authenticate()方法。

(5)调用本类(AbstractAuthenticator)的 doAuthenticate方法

protected AuthenticationInfo doAuthenticate(AuthenticationToken authenticationToken) throws AuthenticationException {this.assertRealmsConfigured();Collection<Realm> realms = this.getRealms();return realms.size() == 1 ? this.doSingleRealmAuthentication((Realm)realms.iterator().next(), authenticationToken) : this.doMultiRealmAuthentication(realms, authenticationToken);}

在该方法中有两个注意点:

a.调用assertRealmsConfigured()方法读取.ini文件中的配置信息。getRealms()方法会返回Realm的个数。

b.判断配置文件中Realm的个数:

  • 如果是一个,则调用doSingleRealmAuthentication()方法。
  • 如果有多个,则调用doMultiRealmAuthentication()方法。

因为在shiro.ini中只配置了一个Realm,所以这里的size=1,进入doSingleRealmAuthentication()方法。

(6)在doSingleRealmAuthentication()方法中调用getAuthenticationInfo()方法。

(7)调用 getCachedAuthenticationInfo()方法,判断缓存中是否有token信息。

(8)如果缓存中没有token信息,调用SimpleAccountRealm类的doGetAuthenticationInfo()方法

(9)SimpleAccountRealm类的doGetAuthenticationInfo()方法实现对用户名的校验。

(10)前面步骤是对用户名的校验,而对密码的校验是在 AuthenticatingRealm类中getAuthenticationInfo()方法。

(11)调用getCredentialsMatcher()方法完成密码校验。

整体流程如下图所示:

针对上述分析,我们可以得到以下结论:

  • 用户名校验是在SimpleAccountRealm的doGetAuthenticationInfo()这个方法完成的。
  • 密码校验是在AuthenticationRealm中的assertCredentialsMatch()方法中完成的。

总结:

  • 认证的Realm:AuthenticationgRealm,需实现的方法doGetAuthenticationInfo()
  • 授权的Realm:AuthorizingRealm,需实现的方法doGetAuthorizationInfo()

2、自定义Realm

(1)主程序

package org.example.shiro;import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.realm.text.IniRealm;
import org.apache.shiro.subject.Subject;public class TestShiro {public static void main(String[] args) {//创建defaultSecurityManagerDefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();//通过读取配置文件设置RealmdefaultSecurityManager.setRealm(new CustomerRealm());//将安装工具类中设置默认安全管理器SecurityUtils.setSecurityManager(defaultSecurityManager);//获取主体对象Subject subject = SecurityUtils.getSubject();//创建token令牌UsernamePasswordToken token = new UsernamePasswordToken("admin", "admin");try{//用户登录subject.login(token);System.out.println("登陆成功");}catch (UnknownAccountException e){e.printStackTrace();System.out.println("用户名错误");}catch (IncorrectCredentialsException e){e.printStackTrace();System.out.println("密码错误");}}
}

(2)自定义Realm

package org.example.shiro;import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;public class CustomerRealm extends AuthorizingRealm {@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {return null;}@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {//在token中获取用户名String principal = (String) authenticationToken.getPrincipal();System.out.println(principal);//这里可以从数据库中读取数据,本程序中只是模拟if("admin".equals(principal)){//参数说明:返回数据库中正确的用户名 返回数据库中的正确密码 提供当前的realm名字SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(principal, "admin", this.getName());return simpleAuthenticationInfo;}return null;}
}

(3)执行结果

Shiro学习笔记(二):自定义Realm的实现相关推荐

  1. Shiro学习笔记_02:shiro的认证+shiro的授权

    Shiro 学习笔记 本文基于B站UP主[编程不良人]视频教程[2020最新版Shiro教程,整合SpringBoot项目实战教程]进行整理记录,仅用于个人学习交流使用. 视频链接:https://w ...

  2. Shiro学习笔记(三)源码解析

    Shiro作为轻量级的权限框架,Shiro的认证流程是怎样的一个过程. 如果没有对Shiro进行了解的话,建议先对Shiro学习笔记(一)学习一下Shiro基本的组 成. 1,几大重要组件解析 1.1 ...

  3. PyTorch学习笔记(二)——回归

    PyTorch学习笔记(二)--回归 本文主要是用PyTorch来实现一个简单的回归任务. 编辑器:spyder 1.引入相应的包及生成伪数据 import torch import torch.nn ...

  4. amazeui学习笔记二(进阶开发4)--JavaScript规范Rules

    amazeui学习笔记二(进阶开发4)--JavaScript规范Rules 一.总结 1.注释规范总原则: As short as possible(如无必要,勿增注释):尽量提高代码本身的清晰性. ...

  5. Vue.js 学习笔记 十一 自定义指令

    之前看到过v-bind,v-on等指令,Vue还可以自定义指<div id="divApp"        <div v-focus></div> & ...

  6. Mongodb使用学习笔记(二)

    文章目录 Mongodb使用学习笔记(二)之查询篇 1. MongoDB命令学习 (1) MongoDB 查询文档 1.1 全部查询 1.2 单条件查询 1.3 多条件查询 1.3.1 AND拼接多条 ...

  7. [MyBatis学习笔记] 二、Mybatis基本操作及相关标签介绍

    [MyBatis学习笔记] 二.Mybatis基本操作及相关标签介绍 一.Mybatis简介 二.简单的CRUD操作 1.构建SqlSessionFactory (1)编辑mybatis-config ...

  8. Spring Boot 框架学习笔记(二)(配置文件与数据注入 yaml基本语法 JSR303数据验证 多环境切换 )

    Spring Boot 框架学习笔记(二) 六.appliaction.properties配置与数据注入 6.1 `@Value`注解 测试注入数据 读取输入流 6.2 读取配置文件数据注入 单文件 ...

  9. qml学习笔记(二):可视化元素基类Item详解(上半场anchors等等)

    原博主博客地址:http://blog.csdn.net/qq21497936 本文章博客地址:http://blog.csdn.net/qq21497936/article/details/7851 ...

  10. [转载]dorado学习笔记(二)

    原文地址:dorado学习笔记(二)作者:傻掛 ·isFirst, isLast在什么情况下使用?在遍历dataset的时候会用到 ·dorado执行的顺序,首先由jsp发送请求,调用相关的ViewM ...

最新文章

  1. 修改文件默认打开方式
  2. Lift当中的AnyVarTrati源码解析
  3. 商业新知产品总监王宇:创业公司不要太看重「增长黑客」运营理念
  4. 【USACO 2.1】The Castle
  5. js模板引擎——art Template
  6. Chrome Android 60.X+ 不能自动播放audio音频的解决办法
  7. linux+top+常用参数,linux的top命令参数详细说明
  8. 固阳一中2021高考成绩查询,中考志愿填报网站
  9. 02-JAVA语法基础
  10. 从武则天的故事看职场生涯规划的一个最重要方面
  11. 0.96寸OLED屏幕控制器SSD1306详解
  12. 黑色炫酷网址安全跳转GO跳转PHP源码
  13. 工科数学分析-微积分(1)
  14. html5 mp4在线播放器,HTML5 Web播放器-Video.js
  15. CF 379F: New Year Tree
  16. BP神经网络实现实例1曲线拟合
  17. [JZOJ4274] [NOIP2015模拟10.28B组] 终章-剑之魂 解题报告(二进制)
  18. nargin与varargin的用法
  19. 管理人员如何有效应用表扬与批评进行反馈
  20. 关于1Byte 1K 1M 1G(换算)

热门文章

  1. 贝叶斯分类器(贝叶斯决策论,极大似然估计,朴素贝叶斯分类器,半朴素贝叶斯分类器,贝叶斯网)学习笔记
  2. Phalcon框架的访问控制列表 ACL(Access Control Lists ACL)
  3. (rear + maxSize - front) % maxSize 公式的理解(文图详解,手把手)
  4. 资源、角色、用户、岗位的关系(工作中用到的)
  5. 天气系统(环境系统)_SLG项目开发经验三
  6. 1072 开学寄语 (20 分)
  7. excel表格同一单元格里删除重复词
  8. 语言-汉语-官话:官话
  9. CDO玩“跨界”,数据驱动有戏了
  10. WEBVTT字幕格式转SRT