你真的了解Shiro框架吗?

关注公众号回复20231110获取最新网络安全以及内网渗透等资料。

在这里插入图片描述

文章目录

    • 关注公众号回复20231110获取最新网络安全以及内网渗透等资料。
    • Shiro的核心架构
    • Shiro中的认证
      • 认证
      • shiro中认证的关键对象
    • 认证流程
    • 调试认证流程
    • Shiro的加密过程
    • Shiro中的解密过程
      • 总结

Shiro的核心架构

在这里插入图片描述

Shiro中的认证

认证

身份认证,就是判断一个用户是否为合法用户的处理过程。最常用的简单身份认证方式是系统通过核对用户输入的用户名和口令,看其是否与系统中存储的该用户的用户名和口令一致,来判断用户身份是否正确。

shiro中认证的关键对象

  • Subject:主体

访问系统的用户,主体可以是用户、程序等,进行认证的都称为主体; ****

  • Principal:身份信息

是主体(subject)进行身份认证的标识,标识必须具有唯一性,如用户名、手机号、邮箱地址等,一个主体可以有多个身份,但是必须有一个主身份(Primary Principal)。

  • credential:凭证信息

是只有主体自己知道的安全信息,如密码、证书等。

认证流程

在这里插入图片描述

调试认证流程

//1.创建安全管理器对象
DefaultSecurityManager securityManager = new DefaultSecurityManager();


//2.给安全管理器设置realm
securityManager.setRealm(new IniRealm("classpath:shiro.ini"));

//3.SecurityUtils 给全局安全工具类设置安全管理器
SecurityUtils.setSecurityManager(securityManager);

//4.关键对象 subject主体
Subject subject = SecurityUtils.getSubject();

//5.去创建令牌
UsernamePasswordToken token = new UsernamePasswordToken("123","123456");


try {
    System.out.println("认证状态:" + subject.isAuthenticated());

    subject.login(token); //用户认证
    System.out.println("登录成功");
    System.out.println("认证状态:" + subject.isAuthenticated());
}catch (UnknownAccountException e){
    System.out.println("用户名不存在");
}catch (IncorrectCredentialsException e){
    System.out.println("密码错误");
}


在subject.login这一行代码打上断点然后我们开始进行调试

可以看到他调用securityManager的login方法 传进去两个参数第一个参数是this 代表当前类对象 第二个token就是我们传进去的AuthenticationToken 就是我们由身份信息和凭证信息组成的令牌 其实我们表面执行的是subject.login方法 其实他底层执行的还是securityManager.login方法 就是我们安全管理器
在这里插入图片描述
继续跟进login方法

可以看到这里调用了authenticate方法 将我们token传进去了 这个方法要么在我们的本类 或者在我们的父类 我们跟进去
在这里插入图片描述

可以看到他调用了父类的authenticate方法
在这里插入图片描述
在这里插入图片描述
我们继续跟进去 来到AbstractAuthenticator的authenticate方法

他上线先去判断我们的令牌是否是null 如果是null直接抛出异常 接着去调用dodoAuthenticate方法 把我们的令牌传进去
在这里插入图片描述
此时来到了ModularRealmAuthenticator类的doAuthenticate方法

首先执行assertRealmsConfigured方法 我们的realm是否配置 我们是在shiro.ini文件是配置过的

然后调用getRealms方法 拿到我们的所有域 然后进行判断 因为我们的size肯定是等于1

然后我们进去doSingleRealmAuthentication方法
在这里插入图片描述
此时来到doSingleRealmAuthentication方法

首先上来先去判断你的realm是否支持token

紧接着调用了realm的getAuthenticationInfo方法 我们跟进去

在这里插入图片描述
来到getAuthenticationInfo方法

这里首先从我们的缓存中去拿数据 因为我们是第一次访问 缓存中肯定是没有数据的 所以肯定是null

所以我们进入if判断

进入doGetAuthenticationInfo方法
在这里插入图片描述
来到SimpleAccountRealm类的doGetAuthenticationInfo方法

这里没有进行循环调用

首先把我们的token取出 然后强制转换为UsernamePasswordToken

接着调用getUser方法 传进去我们token中的用户名 也就是说根据我们token中的用户名去拿用户
在这里插入图片描述
我们跟进进去

首先调用upToken.getUsername()方法 从我们的token中提取到用户名 然后调用getUser方法

这里的this.users 其实就是我们在shiro.ini文件中配置的几个user

这里调用get方法去拿这个用户 如果拿到了就返回SimpleAccount

我们返回
在这里插入图片描述

接着我们返回来 接着判断我们的account是不是空的 我们刚在token中给的用户名是不存在的 所以他自然而然也就为空了 最后进行返回


![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/e2198c16ddb44187abe0dcd8596235fe.png) 小总结:

其实最后调用了这么多方法 最后执行用户名比较 其实是在SimpleAccountRealm类的doGetAuthenticationInfo方法完成了用户名的校验


我们继续往回走继续来到getAuthenticationInfo方法

这里可以看到判断token如果不为空 并且 info也不为空的话 给他放入缓存

之后进行判断如果info不为空的话 调用assertCredentialsMatch方法 将我们的token和info传进去
在这里插入图片描述
我们跟进去assertCredentialsMatch方法

首先拿到了密码匹配器

接着判断我们的密码匹配器是否为空 如果不为空过的话 那么调用密码匹配器的方法去校验

可以看到下面 如果不匹配的话 他会抛异常为IncorrectCredentialsException
在这里插入图片描述
我们跟进去doCredentialsMatch方法

可以看到这里调用了getCredentials方法 将我们的token 以及 info信息传递进去 然后进行equals比较 然后返回

这里是因为我们没有涉及到任何加密 所以使用equals进行比较
在这里插入图片描述

Shiro的加密过程

看以下图:

当我们去登录之后 去访问account page的时候 他会在cookie中带上我们的rememberMe字段 我们主要看他这里是怎么加密的
在这里插入图片描述
经过我们上面说过的他其实是调用了securityManager的login方法 其实最后就是调用了我们的安全管理器里面的login方法

然后他又调用了DefaultSecurityManager的login方法
在这里插入图片描述
我们在这个类中搜索一下有没有rememberMe之类方法

在DefaultSecurityManager类中的rememberMeSuccessfulLogin方法 是对我们rememberMe字段的一些操作

我们现在去点击login去登录 然后debug运行 下断点到这里

在这里插入图片描述
首先他会通过getRememberMeManager方法 获取到RememberMe

然后进行if判断是否为空 如果不为空的话 那么就进入onSuccessfulLogin方法 将我们的token和info 传递进去
在这里插入图片描述
我们跟进去这个方法

可以看到来到了AbstractRememberMeManager类的onSuccessfulLogin方法

这里首先会清除我们的认证信息,然后通过isRememberMe方法 进行判断我们的token中是否有认证信息,

如果有认证信息 那么就进入rememberIdentity方法 我们跟进去
在这里插入图片描述
来到rememberIdentity方法

首先他通过getIdentityToRemember方法 获取到我们token中的用户身份

其实就是我们上面写的这行代码 就是我们的令牌 只是上面的代码时通过shiro.ini文件去拿到域中的 也可以通过数据库之类的

UsernamePasswordToken token = new UsernamePasswordToken("123","123456");

然后我们继续进入rememberIdentity方法
在这里插入图片描述
来到rememberIdentity方法

这里是通过我们的convertPrincipalsToBytes方法 将我们的用户身份 就是我们token中存储的用户身份 也就是用户名 转为byte字节格式

我们跟进去convertPrincipalsToBytes方法
在这里插入图片描述
来到convertPrincipalsToBytes方法

这里首先会将我们的转换为byte字节后的用户身份进行序列化

然后再通过encrypt方法进行加密 我们跟进去在这里插入图片描述
我们来到encrypt方法

这里会通过getCipherService方法获取到密码管理器 然后调用密码管理器的encrypt方法通过密钥进行AES加密

Shiro中有很多加密方式 比如我们常见的md5 salt 散列等等

这里的密钥是通过getEncryptionCipherKey方法获取到的

将我们转换为byte字节后的用户身份(也就是我们的root) 以及序列化之后 然后通过密钥进行AES加密
在这里插入图片描述
我们跟进去getEncryptionCipherKey方法

可以看到他是返回一个encryptionCipherKey 我们看到他是一个属性 类型是byte数组 我们去看哪里对encryptionCipherKey属性进行了赋值
在这里插入图片描述
我们可以看到 这里通过setEncryptionCipherKey方法对encryptionCipherKey属性进行了赋值 我们去看哪里调用了setEncryptionCipherKey方法
在这里插入图片描述
我们来到这里 setCipherKey调用了setEncryptionCipherKey方法 进行了赋值 我们继续找哪里调用了setCipherKey

因为现在这个值我们不知道是多少 所以需要继续往前找
在这里插入图片描述
我们可以清楚的看到 这里通过我们的构造器对encryptionCipherKey进行了赋值

DEFAULT_CIPHER_KEY_BYTES 就是我们的key 我们点进去查看
在这里插入图片描述
可以看到 他的key值是写死的
在这里插入图片描述
convertPrincipalsToBytes方法加密完之后我们进行返回

来到rememberSerializedIdentity方法 我们跟进去
在这里插入图片描述
最后通过Base64编码之后 设置到cookie中
在这里插入图片描述

Shiro中的解密过程

我们来到DefaultSecurityManager类的getRememberedIdentity方法

首先获取到rememberMe 然后进行判断 是否等于空 如果不等于空的话 调用getRememberedPrincipals解密方法

我们跟进去
在这里插入图片描述
来到getRememberedPrincipals方法

这里会调用getRememberedSerializedIdentity和convertBytesToPrincipals方法

getRememberedSerializedIdentity方法 会读取我们的cookie然后进行base64解码 因为我们上面加密的时候 会进行base64编码 到解密这里会进行base64解码

convertBytesToPrincipals方法会对cookie进行解密 并且反序列化
在这里插入图片描述
我们跟进去getRememberedSerializedIdentity方法

这里会调用getCookie获取到cookie之后 然后调用Base64的decode方法进行加密 然后返回
在这里插入图片描述
我们进入到convertBytesToPrincipals方法

这里对我们的解密的base64 byte字节 进行AES解密 并且对他进行反序列化
在这里插入图片描述

总结

到这里Shiro的加密和解密就说完了 其实发现 不管我们认证的过程 还是 AES加密和解密的过程 全都在DefaultSecurityManager类中的一些方法中实现的 紧接着会调用其他类。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/242022.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

ResourceSat2卫星数据下载

印度5米遥感卫星数据开放下载 简介 印度国家遥感中心( NRSC )于近期开放了ResourceSat2卫星的LISS4传感器的数据下载权限,最高分辨率为5米。此次可供下载的有3个波段(近红外/红/绿),下载附带3个GeoTIFF和一个元数据文件&#xf…

计算4*4*4空间中2点结构的分布

不考虑两点距离的情况下,3维空间中的两点最多只有7种位置关系。3条边,3条面对角线,1条体对角线。现在向4*4*4的3维空间中随机的扔2个石子,比较7种结构的占比。 得到表格为 1 96 0.0476 2 96 0.0476 3 288 0.1429 4 288 …

Linux 多版本php ,切换默认版本

1.查看当前默认php版本 ls -l /usr/bin/php 后面的 /usr/local/php/bin/php 表示默认版本 2.查看现在安装了多少版本的php ,可以用 find / -name php 然后切换到到 7.3 版本上 使用命令:ln -sf /usr/local/php7.3/bin/php /usr/bin/php 如果没…

玩转Docker(一):容器生态系统

文章目录 一、核心技术二、平台技术三、支持技术 本文结构如下: 一、核心技术 容器核心技术是指能够让Container在host上运行起来的那些技术。 (1)容器规范 容器不光是Docker,还有其他容器,比如CoreOS的rkt。为了保证…

「Verilog学习笔记」可置位计数器

专栏前言 本专栏的内容主要是记录本人学习Verilog过程中的一些知识点,刷题网站用的是牛客网 timescale 1ns/1nsmodule count_module(input clk,input rst_n,input set,input [3:0] set_num,output reg [3:0]number,output reg zero);reg [3:0] cnt ; always (posed…

AR眼镜_AR智能眼镜整机硬件方案定制

AR眼镜的主要模块包括显示、光学模组、传感器和摄像头、主板、音频和网络连接等。其中,光学显示、主板处理器是决定AR眼镜成本的关键,光机占整体AR眼镜成本43%、处理器占整体成本31%。 AR眼镜的主板设计难点在于尺寸要足够小且要处理好散热问题。主板上的…

VideoComposer:Compositional video synthesis with motion controllability

1.Introduction composer提出了一种一组合性为中心的新的生成范式,能够通过各种输入条件组合生成图像,但是composer主要在空间维度上考虑多级条件。视频复杂的时间结构,其在保持不同帧之间的时间连续性的同时展现出大幅度的时间动态变化。Vi…

【syncfusion】SfGridSplitter 踩坑

SfGridSplitter 是 syncfusion提供的分割线&#xff0c;配合Grid使用可以改变布局大小&#xff1a; <Grid Grid.Row"1"><Grid.ColumnDefinitions><ColumnDefinition Width"1.4*"/><ColumnDefinition MinWidth"10"/><…

Fine-Grained Semantically Aligned Vision-Language Pre-Training细粒度语义对齐的视觉语言预训练

abstract 大规模的视觉语言预训练在广泛的下游任务中显示出令人印象深刻的进展。现有方法主要通过图像和文本的全局表示的相似性或对图像和文本特征的高级跨模态关注来模拟跨模态对齐。然而&#xff0c;他们未能明确学习视觉区域和文本短语之间的细粒度语义对齐&#xff0c;因为…

Linux 中的 container_of 原理

源码基于&#xff1a;Linux 5.10 0.前言 container_of() 这个宏函数在Linux 内核中使用的频率还是很多的。网上关于 container_of 使用的优秀文章也很多&#xff0c;之所以笔者也写一篇&#xff0c;一是想更新下最新代码中的使用&#xff0c;二是融入些自己的拙见&#xff0c;…

排序算法---希尔排序

1. 基本思想 希尔排序是插入排序的一种&#xff0c;它与直接插入排序不同的是&#xff0c;它会优先比较距离较远的元素&#xff0c;因此希尔排序又被称为“缩小增量排序”。希尔排序的实现思路是&#xff1a;先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序&…

VLAN协议与单臂路由

文章目录 VLAN协议与单臂路由一、VLAN的概念及优势1、分割广播域2、VLAN的优势3、VLAN数据帧 二、VLAN的种类1、静态VLAN2、动态VLAN3、VLAN划分方式 三、静态VLAN的配置1、VLAN的范围2、静态VLAN的配置2.1 配置静态VLAN的步骤2.2 vlan三种端口类型举例&#xff1a;配置静态VLA…

代码随想录算法训练营第四十四天 _ 动态规划_完全背包问题、518.零钱兑换II、377.组合总和IV。

学习目标&#xff1a; 动态规划五部曲&#xff1a; ① 确定dp[i]的含义 ② 求递推公式 ③ dp数组如何初始化 ④ 确定遍历顺序 ⑤ 打印递归数组 ---- 调试 引用自代码随想录&#xff01; 60天训练营打卡计划&#xff01; 学习内容&#xff1a; 完全背包问题 – 二维dp数组 动…

nvm 的使用 nvm 可以快速的切换 nodejs 的版本

nvm 是什么&#xff1f; nvm 是一个 node 的版本管理工具&#xff0c;可以简单操作 node 版本的切换、安装、查看。。。等等&#xff0c;与 npm 不同的是&#xff0c;npm 是依赖包的管理工具。 nvm 下载安装 安装之前需要先把 自己电脑上边的 node 给卸载了!!!! 很重要 下载地…

基于Java SSM框架实现个性化影片推荐系统项目【项目源码+论文说明】计算机毕业设计

基于java的SSM框架实现个性化影片推荐系统演示 摘要 随着科学技术的飞速发展&#xff0c;社会的方方面面、各行各业都在努力与现代的先进技术接轨&#xff0c;通过科技手段来提高自身的优势&#xff0c;个性化影片推荐系统当然也不能排除在外。个性化影片推荐系统是以实际运用…

【MySQL】:表的约束(上)

表的约束 一.非空约束二.default约束三.列描述四.zerofill五.主键1.单个主键2.复合主键 真正约束字段的是数据类型&#xff0c;但是数据类型约束很单一&#xff0c;需要有一些额外的约束&#xff0c;更好的保证数据的合法性&#xff0c;从业务逻辑角度保证数据的正确性。比如有…

HCIA-WLAN V3.0,那些重点要点

一、WLAN各个标准&#xff0c;工作频段&#xff0c;理论速率。 二、OFDM和OFDMA&#xff0c;工作频段&#xff0c;空间流。 三、三种帧类型&#xff1a;管理帧、控制帧、数据帧&#xff0c;CAPWAP报文和端口。 四、帧间间隔&#xff0c;波束成形&#xff0c;信道绑定&#xff0…

【obs】官方最强插件obs-websocket入门

▒ 目录 ▒ &#x1f6eb; 导读需求开发环境 1️⃣ obs-websocket简介OBS版本说明obs-websocket版本说明安装&#xff08;27.x版本OBS&#xff09;配置插件 2️⃣ OBS-web介绍特征使用方法-5.xhttp vs https 3️⃣ obs-websocket-js开发tester.html 4️⃣ 其它开源项目obs-stud…

QML中Image动态显示图片内容

1.定义一个ColorImageProvider类 #ifndef COLORIMAGEPROVIDER_H #define COLORIMAGEPROVIDER_H#include <QObject> #include <QImage> #include <QQuickImageProvider>#include <QTimer>class ColorImageProvider :public QObject, public QQuickImag…

线上品牌展厅:打造数字品牌形象,助力品牌宣传

引言&#xff1a; 在数字化时代&#xff0c;随着互联网的普及和电子商务的发展&#xff0c;线上品牌展厅成为越来越多品牌关注的焦点。 一&#xff0e;什么是线上品牌展厅 1.线上品牌展厅的定义 线上品牌展厅是指通过互联网或移动应用程序等在线平台&#xff0c;展示品牌产品…