深入理解 Apache Shiro:安全框架全解析
亲爱的小伙伴们😘,在求知的漫漫旅途中,若你对深度学习的奥秘、JAVA 、PYTHON与SAP 的奇妙世界,亦或是读研论文的撰写攻略有所探寻🧐,那不妨给我一个小小的关注吧🥰。我会精心筹备,在未来的日子里不定期地为大家呈上这些领域的知识宝藏与实用经验分享🎁。每一个点赞👍,都如同春日里的一缕阳光,给予我满满的动力与温暖,让我们在学习成长的道路上相伴而行,共同进步✨。期待你的关注与点赞哟🤗!
一、引言
在当今的软件开发领域,安全是至关重要的一环。无论是企业级应用还是普通的移动应用,都需要保护用户数据和系统资源免受非法访问。Apache Shiro 作为一款强大的 Java 安全框架,提供了全面的安全解决方案,涵盖了身份验证、授权、加密和会话管理等多个方面。在这篇博客中,我们将深入探讨 Shiro 的核心概念、架构以及如何在实际项目中应用它来构建安全的系统。
二、Shiro 核心概念
(一)Subject
Subject 是 Shiro 安全框架的核心概念之一,它代表了当前与系统进行交互的用户或实体。可以将其看作是一个安全上下文的持有者,通过它可以进行身份验证、授权、获取会话等操作。例如,在一个 Web 应用中,当一个用户发起请求时,Shiro 会创建一个对应的 Subject 对象来代表这个用户。
以下是一个简单的代码示例,展示如何获取当前的 Subject:
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;public class ShiroExample {public static void main(String[] args) {// 获取当前 SubjectSubject currentUser = SecurityUtils.getSubject();System.out.println("当前 Subject: " + currentUser);}
}
(二)SecurityManager
SecurityManager 是 Shiro 的核心组件,它负责协调和管理整个安全系统。它是 Shiro 架构的核心枢纽,所有的安全操作都通过它来进行调度和执行。它管理着所有的 Subject、Realm 以及其他安全组件之间的交互。
在 Shiro 的配置中,通常需要创建并配置一个 SecurityManager 实例。例如,在一个基于 Spring 的应用中,可以这样配置:
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"><property name="realm" ref="userRealm"/>
</bean>
这里的 userRealm
是一个自定义的 Realm,用于处理身份验证和授权信息。
(三)Realm
Realm 是 Shiro 进行身份验证和授权的数据源。它负责从数据库、文件系统或其他存储介质中获取用户的身份信息(如用户名、密码)和授权信息(如角色、权限)。可以将 Realm 看作是 Shiro 与实际数据存储之间的桥梁。
例如,我们可以创建一个简单的 Realm 来从内存中获取用户信息:
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;import java.util.HashMap;
import java.util.Map;public class SimpleRealm extends AuthorizingRealm {private Map<String, String> userMap = new HashMap<>();public SimpleRealm() {userMap.put("user1", "password1");userMap.put("user2", "password2");}@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {// 这里可以根据用户信息加载对应的角色和权限信息,暂时为空实现return null;}@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {String username = (String) token.getPrincipal();String password = userMap.get(username);if (password!= null) {return new SimpleAuthenticationInfo(username, password, getName());} else {throw new AuthenticationException("用户不存在");}}
}
三、Shiro 架构
Shiro 的架构设计非常灵活和可扩展,主要由以下几个核心组件组成(如图 1 所示):
- Subject:如前所述,代表当前用户或实体。
- SecurityManager:整个安全系统的核心管理者。
- Realm:数据源,提供身份验证和授权数据。
- Authenticator:负责处理身份验证逻辑,它会调用 Realm 来获取用户信息并进行验证。
- Authorizer:负责处理授权逻辑,根据用户的角色和权限信息来决定是否允许访问特定资源。
- SessionManager:管理用户会话,包括会话的创建、销毁、超时设置等。
当一个 Subject 发起一个安全操作(如访问受保护资源)时,请求会被传递到 SecurityManager。SecurityManager 首先会调用 Authenticator 进行身份验证,如果身份验证成功,再调用 Authorizer 进行授权检查。如果授权通过,Subject 就可以访问相应的资源。
四、身份验证
(一)身份验证流程
身份验证是确定用户身份的过程。在 Shiro 中,通常使用用户名和密码进行身份验证。其基本流程如下:
- 创建一个
UsernamePasswordToken
,包含用户名和密码信息。 - 获取当前的 Subject。
- 通过 Subject 的
login
方法传入UsernamePasswordToken
进行身份验证。
以下是代码示例:
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;public class AuthenticationExample {public static void main(String[] args) {Subject currentUser = SecurityUtils.getSubject();// 创建用户名密码令牌UsernamePasswordToken token = new UsernamePasswordToken("user1", "password1");try {// 进行身份验证currentUser.login(token);System.out.println("身份验证成功");} catch (Exception e) {System.out.println("身份验证失败: " + e.getMessage());}}
}
(二)自定义身份验证策略
Shiro 允许我们自定义身份验证策略,以满足不同的业务需求。例如,我们可以实现一个多 Realm 身份验证策略,当多个 Realm 存在时,根据不同的规则来确定身份验证是否成功。
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.pam.ModularRealmAuthenticator;
import org.apache.shiro.realm.Realm;import java.util.ArrayList;
import java.util.Collection;public class MyModularRealmAuthenticator extends ModularRealmAuthenticator {@Overrideprotected AuthenticationInfo doAuthenticate(AuthenticationToken authenticationToken) throws AuthenticationException {// 获取所有的 RealmCollection<Realm> realms = getRealms();if (realms == null || realms.isEmpty()) {throw new AuthenticationException("没有配置 Realm");}ArrayList<AuthenticationInfo> infoList = new ArrayList<>();for (Realm realm : realms) {// 每个 Realm 进行身份验证AuthenticationInfo info = realm.getAuthenticationInfo(authenticationToken);if (info!= null) {infoList.add(info);}}if (infoList.isEmpty()) {throw new AuthenticationException("身份验证失败");} else if (infoList.size() == 1) {return infoList.get(0);} else {// 自定义多 Realm 身份验证成功的逻辑,这里简单返回第一个return infoList.get(0);}}
}
五、授权
(一)基于角色的授权
Shiro 支持基于角色的授权,即根据用户所属的角色来决定是否允许访问资源。首先需要在 Realm 中加载用户的角色信息,然后在代码中通过 hasRole
等方法进行授权检查。
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;public class AuthorizationExample {public static void main(String[] args) {Subject currentUser = SecurityUtils.getSubject();if (currentUser.hasRole("admin")) {System.out.println("用户具有管理员角色,可以访问特定资源");} else {System.out.println("用户没有管理员角色,无权访问");}}
}
(二)基于权限的授权
除了基于角色,Shiro 还支持基于权限的授权,更加细粒度地控制资源访问。权限可以是对某个操作或资源的特定许可。
例如,在 Realm 中加载用户的权限信息后,可以这样进行授权检查:
if (currentUser.isPermitted("user:create")) {System.out.println("用户有权创建用户");
} else {System.out.println("用户无权创建用户");
}
六、会话管理
Shiro 提供了强大的会话管理功能,可以管理用户的会话状态,包括会话的创建、销毁、超时设置等。
在 Web 应用中,可以通过配置 SessionManager
来定制会话管理策略。例如:
<bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager"><property name="globalSessionTimeout" value="1800000"/> <!-- 会话超时时间,单位毫秒 -->
</bean>
在代码中,可以通过 Subject 获取会话对象并进行操作:
Subject currentUser = SecurityUtils.getSubject();
// 获取会话
org.apache.shiro.session.Session session = currentUser.getSession();
session.setAttribute("userData", "一些用户数据");
String data = (String) session.getAttribute("userData");
System.out.println("会话中的数据: " + data);
七、加密
Shiro 提供了方便的加密工具,用于对敏感数据(如密码)进行加密存储和传输。
例如,使用 Shiro 的 Md5Hash
对密码进行加密:
import org.apache.shiro.crypto.hash.Md5Hash;public class EncryptionExample {public static void main(String[] args) {String password = "password1";// 使用 Md5 加密密码,可指定盐值Md5Hash md5Hash = new Md5Hash(password, "salt");System.out.println("加密后的密码: " + md5Hash.toHex());}
}
八、总结
Apache Shiro 是一款功能强大、灵活且易于使用的 Java 安全框架。通过深入理解其核心概念(如 Subject、SecurityManager、Realm)、架构以及身份验证、授权、会话管理和加密等关键功能,我们可以在实际项目中有效地构建安全可靠的系统。无论是简单的单体应用还是复杂的分布式系统,Shiro 都能提供合适的安全解决方案,帮助我们保护用户数据和系统资源免受各种安全威胁。在后续的开发中,我们可以根据具体的业务需求进一步探索 Shiro 的高级特性和定制化配置,以构建更加完善的安全体系。
相关文章:

深入理解 Apache Shiro:安全框架全解析
亲爱的小伙伴们😘,在求知的漫漫旅途中,若你对深度学习的奥秘、JAVA 、PYTHON与SAP 的奇妙世界,亦或是读研论文的撰写攻略有所探寻🧐,那不妨给我一个小小的关注吧🥰。我会精心筹备,在…...

mac 安装CosyVoice (cpu版本)
CosyVoice 介绍 CosyVoice 是阿里研发的一个tts大模型 官方项目地址:https://github.com/FunAudioLLM/CosyVoice.git 下载项目(非官方) git clone --recursive https://github.com/v3ucn/CosyVoice_for_MacOs.git 进入项目 cd CosyVoic…...

币安移除铭文市场的深度解读:背后原因及其对区块链行业的影响
引言: 就在昨天,2024年12月10号,币安宣布将移除铭文市场(Inscriptions Market)。这一消息引发了全球加密货币社区的广泛关注,尤其是在比特币NFT和数字收藏品市场快速发展的背景下。铭文市场自诞生以来迅速…...

深度学习实战野生动物识别
本文采用YOLOv11作为核心算法框架,结合PyQt5构建用户界面,使用Python3进行开发。YOLOv11以其高效的实时检测能力,在多个目标检测任务中展现出卓越性能。本研究针对野生动物数据集进行训练和优化,该数据集包含丰富的野生动物图像样…...

windows安装使用conda
在Windows系统上安装和使用Conda的详细步骤如下: 一、下载Conda安装包 访问Conda的官方网站Anaconda | The Operating System for AI,点击“Downloads”按钮。在下载页面,选择适合您系统的安装包。通常,对于Windows系统…...

手机租赁系统开发全流程解析与实用指南
内容概要 在如今快速发展的科技时代,手机租赁系统已经成为一种新兴的商业模式,非常符合当下市场需求。那么,在开发这样一个系统的时候,首先要从需求分析和市场调研开始。在这一阶段,你需要了解用户需要什么࿰…...

SpringBoot 开发—— YAML文件深度分析
文章目录 一、YAML概述二、数据表示三、YAML 的语法四、YAML 的应用五、YAML 与其他格式的比较1、YAML vs .properties文件可读性和结构数据类型支持扩展性和灵活性使用场景性能和支持2、YAML vs. JSON3、YAML vs. XML六、使用 YAML 的注意事项七、总结YAML 是非常流行的一种配…...

复合机器人整体解决方案
复合机器人是一种集成移动机器人和协作机器人两项功能为一身的新型机器人,更符合人们想象中“脑、眼、手、脚”融合的机器人终极形态。复合机器人的整体解决方案通常涉及多个方面,包括机器人本体、控制系统、感知系统、执行系统以及周边配套设备等。以下…...

【Oracle11g SQL详解】日期和时间函数:SYSDATE、TO_DATE、TO_CHAR 等
日期和时间函数:SYSDATE、TO_DATE、TO_CHAR 等 在 Oracle 数据库中,日期和时间函数用于处理日期和时间数据。它们在记录创建时间、分析时间间隔、格式化输出等场景中非常重要。本文将详细讲解常用的日期和时间函数及其应用。 一、SYSDATE:获…...

VSCode设置字体
参考文章:【面向小白】vscode最佳实践(2)—— 字体设置(fira code更纱黑体),这篇文章末尾给了安装字体的链接。 配置的字体还是很好看的。 ‘Fira Code Retina’, ‘Sarasa Mono Sc’ 需要注意的一个点&am…...

shell编程入门之提取字符并设置rtc时间
awk用法 awk是一款文本处理工具,通常在Unix和Linux操作系统中使用,用于以行为单位对文本进行处理和操作。它可以读取输入文本,对其进行处理,生成报表、统计信息等,并将结果输出到标准输出设备中。 它主要有以下特点&…...

react 不可变数据更新(Immutable Update)合并对象 类似与Java 的BeanUtils.copyProperties
{ ...state, // 保留原有的 state 的其他部分data: { ...state.data, // 保留 state.data 中的其他字段...action.payload // 使用 action.payload 覆盖 state.data 中需要更新的字段} }这段代码是 Redux 中常见的一种状态更…...

Linux GCC基础用法⑦
在 CentOS 7 系统中使用 GCC 与编写 99 乘法表 一、GCC 简介 GCC(GNU Compiler Collection)是一套功能强大的编程语言编译器,在 CentOS 7 系统中广泛用于编译 C、C等多种编程语言的程序。它能够将源代码转换为可执行文件,让计算…...

PyTorch 切片运算 (Slice Operator)
PyTorch 切片运算 {Slice Operator} 1. [:, -1, :]2. [:, [-1], :]References 1. [:, -1, :] https://github.com/karpathy/llama2.c/blob/master/model.py import torchlogits torch.arange(1, 16) print("logits.shape:", logits.shape) print("logits:\n&…...

SpringSecurity Oauth2 -账号密码实现多因子身份认证
1. 密码策略问题 CREATE TABLE t_storage (id bigint(20) NOT NULL AUTO_INCREMENT COMMENT 自增主键,nameSpace varchar(64) NOT NULL COMMENT 隔离字段,groupId varchar(128) NOT NULL COMMENT 分组,比如不同app,dataId varchar(64) NOT NULL COMMENT 数据存储id…...

【CSS in Depth 2 精译_071】11.4 思考字体颜色的对比效果 + 11.5 本章小结
当前内容所在位置(可进入专栏查看其他译好的章节内容) 第四部分 视觉增强技术 ✔️【第 11 章 颜色与对比】 ✔️ 11.1 通过对比进行交流 11.1.1 模式的建立11.1.2 还原设计稿 11.2 颜色的定义 11.2.1 色域与色彩空间11.2.2 CSS 颜色表示法 11.2.2.1 RGB…...

Y3编辑器文档4:触发器1(对话、装备、特效、行为树、排行榜、不同步问题)
文章目录 一、触发器简介1.1 触发器界面1.2 ECA语句编辑及快捷键1.3 参数设置1.4 变量设置1.5 实体触发器1.6 函数库与触发器复用 二、触发器的多层结构2.1 子触发器(在游戏内对新的事件进行注册)2.2 触发器变量作用域2.3 复合条件2.4 循环2.5 计时器2.6…...

趣味编程:猜拳小游戏
1.简介 这个系列的第一篇以猜拳小游戏开始,这是源于我们生活的灵感,在忙碌的时代中,我们每个人都在为自己的生活各自忙碌着,奔赴着自己所走向的那条路上,即使遍体鳞伤。 但是,生活虽然很苦,也不…...

软件工程 概述
软件 不仅仅是一个程序代码。程序是一个可执行的代码,它提供了一些计算的目的。 软件被认为是集合可执行的程序代码,相关库和文档的软件。当满足一个特定的要求,就被称为软件产品。 工程 是所有有关开发的产品,使用良好定义的&…...

CountDownLatch阻塞后countDown未执行会如何?
背景 某项目封装了 Kafka 消费者 API,根据传递的消费者线程数,创建 N 个消费者线程同时消费对应 topic 的数据,并在线程启动后收集到全局列表中,方便在程序调用 stop 流程时逐个停止。 主控类在创建 Kafka 消费线程时使用了 Cou…...

k8s,operator
相对更加灵活和编程友好的管理“有状态应用”的解决方案,它就是:Operator 会议一下有状态应用: 比如数据库集群,数据挂载需要有顺序维护拓扑关系的应用 使用statefulSet这个对象来描述。 CRD又是什么? Operator的工作…...

使用 pyperclip 进行跨平台剪贴板操作
简介:pyperclip 是一个轻量级的 Python 库,支持在不同操作系统(Windows、macOS、Linux)中进行剪贴板的复制和粘贴。这个库的设计简单易用,非常适合需要频繁进行文本复制粘贴操作的场景。 历史攻略: 使用f…...

20 设计模式之职责链模式(问题处理案例)
一、什么是职责链模式 职责链模式是一种行为型设计模式,它允许将请求沿着处理者的链进行传递,直到有一个处理者能够处理它为止。换句话说,它将请求的发送者和接收者解耦,使得多个对象都有机会处理这个请求,从而避免了将…...

SpringBoot3集成MybatisPlus3和knife4j(swagger3兼容增强版)
针对Swagger2规范和OpenAPI3规范的说明: 在Spring Boot框架中,Knife4j对于服务端将Spring的开放接口解析成Swagger2或者OpenAPI3规范的框架,也是依赖的第三方框架组件。说明如下: Swagger2规范:依赖Springfox项目,该项目目前几乎处于停更状态,但很多老项目依然使用的是该…...

【MIT-OS6.S081作业1.3】Lab1-utilities primes
本文记录MIT-OS6.S081 Lab1 utilities 的primes函数的实现过程 文章目录 1. 作业要求primes (moderate)/(hard) 2. 实现过程2.1 代码实现 1. 作业要求 primes (moderate)/(hard) Write a concurrent version of prime sieve using pipes. This idea is due to Doug McIlroy, in…...

游戏引擎学习第35天
开场介绍 今天的任务是继续改进一个虚拟的瓦片地图系统,使其适合处理更大的世界。我们希望这个系统能管理大范围的游戏世界,其中包含按需存储的小区域。昨天,我们介绍了“内存区域”的概念,用于管理持久性存储。我们计划今天继续…...
learn-(Uni-app)输入框u-search父子组件与input输入框(防抖与搜索触发)
1.父子组件u-search (1)父组件 <!-- 父组件 --> <template> <div><searchBar change"change" search"search"></searchBar> </div> </template> <script> // 子组件搜索 import…...

设置IMX6ULL开发板的网卡IP的两种方法(临时生效和永久有效两种方法)
设置开发板网卡的IP,有两种方法。 方法一:临时生效 第一种方式是临时设置,只有本次有效,重启后又要重新设,命令为: ifconfig eth0 192.168.5.9设置成功后可以使用ifconfig命令来查看已设置的 IP 地址。 …...

流量转发利器之Burpsuite概述(1)
目录 一、Burpsuite Burp Suite Spider 的主要特点: 在 Burp Suite 中使用 Spider: Spider 的用例: 限制: 声明:学习视频来自b站up主 泷羽sec,如涉及侵权马上删除文章 声明:本文主要用作技…...

Transformer入门(6)Transformer编码器的前馈网络、加法和归一化模块
文章目录 7.前馈网络8.加法和归一化组件9.组合所有编码器组件构成完整编码器 7.前馈网络 编码器块中的前馈网络子层如下图所示: 图1.32 – 编码器块 前馈网络由两个带有ReLU激活函数的全连接层组成。全连接层(Fully Connected Layer)有时也…...