Shiro学习笔记(二):自定义Realm的实现
上一篇文章中提到了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的实现相关推荐
- Shiro学习笔记_02:shiro的认证+shiro的授权
Shiro 学习笔记 本文基于B站UP主[编程不良人]视频教程[2020最新版Shiro教程,整合SpringBoot项目实战教程]进行整理记录,仅用于个人学习交流使用. 视频链接:https://w ...
- Shiro学习笔记(三)源码解析
Shiro作为轻量级的权限框架,Shiro的认证流程是怎样的一个过程. 如果没有对Shiro进行了解的话,建议先对Shiro学习笔记(一)学习一下Shiro基本的组 成. 1,几大重要组件解析 1.1 ...
- PyTorch学习笔记(二)——回归
PyTorch学习笔记(二)--回归 本文主要是用PyTorch来实现一个简单的回归任务. 编辑器:spyder 1.引入相应的包及生成伪数据 import torch import torch.nn ...
- amazeui学习笔记二(进阶开发4)--JavaScript规范Rules
amazeui学习笔记二(进阶开发4)--JavaScript规范Rules 一.总结 1.注释规范总原则: As short as possible(如无必要,勿增注释):尽量提高代码本身的清晰性. ...
- Vue.js 学习笔记 十一 自定义指令
之前看到过v-bind,v-on等指令,Vue还可以自定义指<div id="divApp" <div v-focus></div> & ...
- Mongodb使用学习笔记(二)
文章目录 Mongodb使用学习笔记(二)之查询篇 1. MongoDB命令学习 (1) MongoDB 查询文档 1.1 全部查询 1.2 单条件查询 1.3 多条件查询 1.3.1 AND拼接多条 ...
- [MyBatis学习笔记] 二、Mybatis基本操作及相关标签介绍
[MyBatis学习笔记] 二.Mybatis基本操作及相关标签介绍 一.Mybatis简介 二.简单的CRUD操作 1.构建SqlSessionFactory (1)编辑mybatis-config ...
- Spring Boot 框架学习笔记(二)(配置文件与数据注入 yaml基本语法 JSR303数据验证 多环境切换 )
Spring Boot 框架学习笔记(二) 六.appliaction.properties配置与数据注入 6.1 `@Value`注解 测试注入数据 读取输入流 6.2 读取配置文件数据注入 单文件 ...
- qml学习笔记(二):可视化元素基类Item详解(上半场anchors等等)
原博主博客地址:http://blog.csdn.net/qq21497936 本文章博客地址:http://blog.csdn.net/qq21497936/article/details/7851 ...
- [转载]dorado学习笔记(二)
原文地址:dorado学习笔记(二)作者:傻掛 ·isFirst, isLast在什么情况下使用?在遍历dataset的时候会用到 ·dorado执行的顺序,首先由jsp发送请求,调用相关的ViewM ...
最新文章
- 修改文件默认打开方式
- Lift当中的AnyVarTrati源码解析
- 商业新知产品总监王宇:创业公司不要太看重「增长黑客」运营理念
- 【USACO 2.1】The Castle
- js模板引擎——art Template
- Chrome Android 60.X+ 不能自动播放audio音频的解决办法
- linux+top+常用参数,linux的top命令参数详细说明
- 固阳一中2021高考成绩查询,中考志愿填报网站
- 02-JAVA语法基础
- 从武则天的故事看职场生涯规划的一个最重要方面
- 0.96寸OLED屏幕控制器SSD1306详解
- 黑色炫酷网址安全跳转GO跳转PHP源码
- 工科数学分析-微积分(1)
- html5 mp4在线播放器,HTML5 Web播放器-Video.js
- CF 379F: New Year Tree
- BP神经网络实现实例1曲线拟合
- [JZOJ4274] [NOIP2015模拟10.28B组] 终章-剑之魂 解题报告(二进制)
- nargin与varargin的用法
- 管理人员如何有效应用表扬与批评进行反馈
- 关于1Byte 1K 1M 1G(换算)
热门文章
- 贝叶斯分类器(贝叶斯决策论,极大似然估计,朴素贝叶斯分类器,半朴素贝叶斯分类器,贝叶斯网)学习笔记
- Phalcon框架的访问控制列表 ACL(Access Control Lists ACL)
- (rear + maxSize - front) % maxSize 公式的理解(文图详解,手把手)
- 资源、角色、用户、岗位的关系(工作中用到的)
- 天气系统(环境系统)_SLG项目开发经验三
- 1072 开学寄语 (20 分)
- excel表格同一单元格里删除重复词
- 语言-汉语-官话:官话
- CDO玩“跨界”,数据驱动有戏了
- WEBVTT字幕格式转SRT