Shiro学习(一):Shiro介绍和基本使用

一、Shiro介绍

1、百科对shiro的定义如下:

Apache Shiro 一个强大且易于使用的 Java 安全框架,它提供了身份验证、授权、加密和会话管理等功能。Shiro 的设计目标是简化企业级应用程序的安全性开发过程,同时保持代码的简洁和易于维护。

2、Shiro 核心功能介绍

2.1、Authentication(认证)

        认证和授权是Shiro最核心的功能,认证操作主要用来处理2方便的工作,即:

             1)验证用户身份,如:用户名密码、OAuth、LDAP等。

                  LDAP(轻量级目录访问协议)种在互联网上标准的数据协议,用于访问和维护分布式

                  目录信息服务。在许多企业和组织中,LDAP被用来存储用户认证信息,如用户名、密

                  码、电子邮件地址等,用于实现LDAP统一用户认证和单点登录

             2)支持多 Realm(数据源),如数据库、LDAP、Active Directory 等。

2.2、Authorization(授权)

       授权主要用来做 :

       1)基于角色(Role)和权限(Permission)的资源控制访问

       2)支持细粒度的权限控制,如:user:create、file:edit等

2.3、Session Management(会话管理)

        会话管理主要用来做:

         1)提供会话管理,即使没有 Web 容器(如 Tomcat)也能使用。

         2)支持分布式会话,如:Redis缓存。

2.4、Cryptography(加密)

       1)Shiro加密模块提供哈希(如 MD5、SHA)、加解密(AES、DES)等工具。

       2)Shiro支持密码加盐(Salt)和多次哈希迭代

2.5、Web Integration(Web集成)

       1)提供 ShiroFilter 拦截请求,实现 URL 级别的安全控制

       2)支持 RESTful API 安全认证(如 JWT 集成)

2.6、Cache(缓存)

       1)Shiro 支持缓存认证和授权信息,提高性能(如 Redis、Ehcache)。

3、Shiro 核心角色和架构:

3.1、Shiro 核心架构图如下:

        

3.2、Shiro 核心角色如下:

       1)Subject

            表示当前“用户”,Subject 用户并不是单单指登录程序的user;与程序交互的任何主体都是

            Subject用户,如:网络爬虫、user、机器设备等等。

            所有的Subject 用户都由 SecurityManager管理,Subject由当前线程绑定(通过

            ThreadLocal实现),即Subject 是线程安全的;

            Shiro 是所有安全操作的入口;在开发中通常通过Shiro的工具类SecurityUtils.getSubject()

            来获取Subject,如下图所示:

                  

       2)SecurityManager

             SecurityManager 是Shrio 的核心,管理所有的安全操作,协调所有安全组件,

              如:认证、授权、会话管理。

             在Shiro 中 SecurityManager 的重要实现有2个,即:

                  1)DefaultSecurityManager    默认实现

                  2)SessionsSecurityManager  支持会话管理

       3)Authenticator

            认证器,用于Subject用户的认证逻辑;

            Shiro 默认实现是 ModularRealmAuthenticator

            认证流程:

               (1)用户提交凭证(如 UsernamePasswordToken)。

               (2)Authenticator 调用 Realm 的 doGetAuthenticationInfo() 方法。

               (3)匹配凭证与 Realm 返回的数据(如密码加盐哈希比较)。

       4)Authorizer

             授权器,用于判断认证通过的用户是否具有某些资源的访问权限的过程;

             Shiro 支持基于角色和权限的资源访问控制。

             Shiro 的默认实现是 ModularRealmAuthorizer

       5)SessionManager

             管理Session 生命周期的组件,是Shiro 自带的session会话管理器,这就表示即使在非

             Web环境中也可以使用Shiro进行认证和授权。

             Shiro中 SessionManager 的核心实现如下:

                  (1)DefaultSessionManager(默认实现)

                  (2)ServletContainerSessionManager(委托给 Servlet 容器,如 Tomcat)

                  (3)EnterpriseCacheSessionManager(支持分布式缓存,如 Redis)

       

       6)CacheManager

              该组件用于缓存认证、授权、角色、会话等的数据,提升性能。

              Shiro中默认的实现有:

                 (1)MemoryConstrainedCacheManager(内存缓存)

                 (2)EhCacheManager(集成 Ehcache)

                 (3)RedisCacheManager(将数据缓存到Redis,分布式缓存)

       7)Realm 

            Realm,安全数据源, 是连接Shiro 与 安全数据的桥梁(如:JDBC数据库数据、LADP、

            内存数据);用于获取安全数据进行认证、授权;

            Realm 可以有多个,由用户自己提供;一般应用中需要用户定义自己的Realm;

            Shiro默认提供了3个Realm 实现,即:

                   1)IniRealm:基于 .ini文件的配置,从Shiro.ini读取用户 认证/授权 和 角色数据

                   2)JdbcRealm:通过JDBC查询数据库中的安全数据(认证/授权 相关的数据)

                   3)TextConfigurationRealm:安全数据配置在内存中,用于替代 IniRealm

       8)Filter

           Web过滤器,在 Web 环境中拦截请求,实现 URL 级别的安全控制

二、Shiro 简单使用

下边分别以 SimpleAccountRealm、IniRealm、JdbcRealm、自定义Realm 分别来演示下Shiro

认证和授权的基本流程。

     1)认证流程

            

     2)授权流程

           

1、SimpleAccountRealm

      SimpleAccountRealm是Shiro 提供的一个最基本的 Realm 内存实现,适用于快速原型开发

       或测试场景。它直接在内存储存用户、角色和权限信息,无需连接数据库或外部配置。

      示例代码如下:

@Testpublic void authen(){/*** 认证需要准备3个角色* 1)认证得发起者(一般叫Subject)* 2)SecurityManager* 3)Realm* 认证发起者得能够找到 SecurityManager,SecurityManager得能够找到 Realm,所以这三者需要存在依赖关系** 认证流程如下:*///1、准备 RealmSimpleAccountRealm realm = new SimpleAccountRealm();//添加用户//模拟拿到用户信息:用户名称、密码、角色信息realm.addAccount("admin","123456","超级管理员","商家");//2、准备 SecurityManagerDefaultSecurityManager securityManager = new DefaultSecurityManager();//3、SecurityManager 与 Realm 建立连接securityManager.setRealm(realm);//4、Subject 与 SecurityManager 建立链接SecurityUtils.setSecurityManager(securityManager);//5、准备 SubjectSubject subject = SecurityUtils.getSubject();//6、发起认证,认证失败抛出异常 AuthenticationException,认证通过不抛出异常subject.login(new UsernamePasswordToken("admin","123456"));//7、判断是否认证成功System.out.println(subject.isAuthenticated());//8、判断用户角色boolean b1 = subject.hasRole("超级管理员");//判断是否有超级管理员角色//使用 checkRole/checkRoles判断角色时,若角色不存在,则会抛出异常AuthorizationException// SimpleAccountRealm只支持角色的授权System.out.println("是否拥有超级管理员角色:" +b1);subject.checkRole("商家");//9、退出校验subject.logout();}

2、IniRealm

      IniRealm 是基于文件存储的授权认证,IniRealm 可以将用户的用户名、密码、角色信息存储

      到.ini文件中,来实现持久化;所示使用IniRealm 需要先准备一个.ini文件,如:Shiro.ini;

     Shiro.ini 文件内容如下:

           

      示例代码如下:

@Testpublic void authen(){//1、构建 RealmIniRealm realm = new IniRealm("classpath:shiro.ini");//2、构建 SecurityManager 并绑定RealmDefaultSecurityManager securityManager = new DefaultSecurityManager();securityManager.setRealm(realm);//3、基于 SecurityUtils 绑定 SecurityManager 并声明认证主题(即认证发起者)SubjectSecurityUtils.setSecurityManager(securityManager);Subject subject = SecurityUtils.getSubject();//4、执行认证操作subject.login(new UsernamePasswordToken("admin","123456"));//5、角色校验boolean b1 = subject.hasRole("超级管理员");//判断是否有超级管理员角色System.out.println(b1);//6、权限校验//权限校验失败会抛出异常subject.checkPermission("user:add");subject.checkPermission("user:select");}

3、JdbcRealm

     JdbcRealm 是把认证授权的数据保存到数据库中,所以基于JdbcRealm的认证授权需要连接

     数据库,示例代码如下:

    

@Testpublic void authen(){//1、构建RealmJdbcRealm realm = new JdbcRealm();//设置数据源DruidDataSource dataSource = new DruidDataSource();dataSource.setDriverClassName("com.mysql.jdbc.Driver");dataSource.setUrl("jdbc:mysql://47.100.7.152:3306/shiro");dataSource.setUsername("javademo");dataSource.setPassword("123qwe!@#");realm.setDataSource(dataSource);//开启权限校验,JdbcRealm 默认是不能进行权限校验的realm.setPermissionsLookupEnabled(true);/*** JdbcRealm 自定义 认证查询、权限查询、角色查询sql*///认证查询sql//realm.setAuthenticationQuery(sql);//权限查询sql//realm.setPermissionsQuery(sql);//角色查询sql//realm.setUserRolesQuery(sql);//2、构建 SecurityManager,并绑定RealmDefaultSecurityManager securityManager = new DefaultSecurityManager();securityManager.setRealm(realm);//3、并基于SecurityUtil 绑定SecurityManager,并声明主题(认证者)SubjectSecurityUtils.setSecurityManager(securityManager);Subject subject = SecurityUtils.getSubject();//4、执行认证操作subject.login(new UsernamePasswordToken("admin","123456"));//5. 授权操作(角色)System.out.println(subject.hasRole("超级管1理员"));//6. 授权操作(权限)System.out.println(subject.isPermitted("user:add"));}

4、CustomRealm

      CustomRealm是一个自定义的Realm;

      自定义Realm 一般需要继承 AuthorizingRealm 并重写方法doGetAuthenticationInfo(授权)与

      方法doGetAuthenticationInfo(认证)

     示例代码如下:

/***************************************************** 模拟JdbcRealm 自定义 Realm(即 CustomRealm) 来完成认证和授权* 自定义 CustomRealm 需要继承 AuthorizingRealm 并实现 AuthorizingRealm 的2个* 核心方法:doGetAuthorizationInfo 和 doGetAuthenticationInfo** @author lbf* @date ****************************************************/
public class CustomRealm extends AuthorizingRealm {/*** 授权* todo 注意:*    授权是在认证之后的操作,授权方法需要用到认证方法返回的 AuthenticationInfo  中的用户信息** @param principals  即 doGetAuthenticationInfo 方法返回的 AuthenticationInfo 中的用户信息(这里是User )* @return*/@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {//1. 获取认证用户的信息User user = (User) principals.getPrimaryPrincipal();//2. 基于用户信息获取当前用户拥有的角色。Set<String> roleSet = this.findRolesByUser();//3. 基于用户拥有的角色查询权限信息Set<String> permSet = this.findPermsByRoleSet(roleSet);//4. 声明AuthorizationInfo对象作为返回值,传入角色信息和权限信息SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();info.setRoles(roleSet);info.setStringPermissions(permSet);//5. 返回return info;}private Set<String> findPermsByRoleSet(Set<String> roleSet) {Set<String> set = new HashSet<>();set.add("user:add");set.add("user:update");return set;}private Set<String> findRolesByUser() {Set<String> set = new HashSet<>();set.add("超级管理员");set.add("运营");return set;}/*** 认证 用户执行认证操作传入的用户名和密码* 只需要完成用户名校验即可,密码校验由Shiro内部完成** @param token* @return* @throws AuthenticationException*/@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {//1、获取用户名称String userName = (String) token.getPrincipal();//2、判断用户名称是否为空if(StringUtils.isEmpty(userName)){// 返回null,会默认抛出一个异常,org.apache.shiro.authc.UnknownAccountExceptionreturn null;}//4、如果用户名称不为空,则基于用户名称去查询用户信息//这一步一般是自己的UserService 服务//模拟查询用户信息User user = this.findUserByUsername(userName);if(user == null){return null;}//5、构建 AuthenticationInfo 对象,并填充用户信息/*** todo 注意:*    SimpleAuthenticationInfo 第一个参数是用户信息,第二个参数是用户密码,第三个参数是Realm名称(这个参数没有意义)*/SimpleAuthenticationInfo info =  new SimpleAuthenticationInfo(user,user.getPassword(),"CustomRealm!!!");//返回 AuthenticationInfo 对象return info;}// 模拟数据库操作private User findUserByUsername(String username) {if("admin".equals(username)){User user = new User();user.setId(1);user.setUsername("admin");user.setPassword("admin");return user;}return null;}
}public class User {private Integer id;private String username;private String password;
}

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java多线程与高并发专题——关于Condition

Condition接口 源码注释 还是老样子&#xff0c;看看源码注释&#xff1a; Condition factors out the Object monitor methods (wait, notify and notifyAll) into distinct objects to give the effect of having multiple wait-sets per object, by combining them with t…

JavaScript 性能优化实战:突破瓶颈,打造极致 Web 体验

在当今快节奏的互联网时代&#xff0c;用户对于 Web 应用的性能要求越来越高。一个响应迅速、流畅运行的 Web 页面能够极大地提升用户体验&#xff0c;反之&#xff0c;缓慢的加载速度和卡顿的交互则可能导致用户流失。JavaScript 作为 Web 开发的核心语言之一&#xff0c;其性…

《白帽子讲 Web 安全》之服务端请求伪造(SSRF)深度剖析:从攻击到防御

引言 在当今复杂的网络环境中&#xff0c;Web 应用安全犹如一座时刻需要精心守护的堡垒。随着技术的不断演进&#xff0c;各类安全威胁层出不穷&#xff0c;其中服务端请求伪造&#xff08;SSRF&#xff09;正逐渐成为令开发者与安全从业者头疼的一大难题。吴翰清在《白帽子讲…

Pandas的轴,axis=0,axis=1

八. Pandas的轴 axis0代表跨行&#xff08;down)&#xff0c;而axis1代表跨列&#xff08;across) 使用0值表示沿着每一列或行标签\索引值向下执行方法使用1值表示沿着每一行或者列标签模向执行对应的方法 下图代表在DataFrame当中axis为0和1时分别代表的含义: axis参数作用…

matplotlib学习

开始学习Python数据可视化 一.基础绘图函数 1.创建画布与坐标轴 import matplotlib.pyplot as plt# 创建画布和坐标轴 fig, ax plt.subplots() # 默认1行1列&#xff0c;返回Figure对象和Axes对象 2.绘制线图 x [1, 2, 3, 4] y [10, 20, 15, 25]# 绘制线图 ax.plot(x,…

系统架构设计前的多角度思考

首先&#xff0c;从需求分析入手&#xff0c;不仅关注当前功能&#xff0c;还要考虑业务未来的扩展方向。比如数据量预估增长多少&#xff1f;这些都是影响架构的重要因素。 然后是架构设计原则&#xff0c;比如分层设计、模块化、高内聚低耦合等。比如如何划分服务边界&#x…

leetcode230.二叉搜索树中第k小的元素

中序遍历&#xff0c;第k次出现的数值就是结果 /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(nullptr) {}* TreeNode(int x) : val(x), left…

运筹说 第134期 | 矩阵对策的解法

上一期我们了解了矩阵对策的基本理论&#xff0c;包含矩阵对策的纯策略、矩阵对策的混合策略和矩阵对策的基本定理。 接下来小编将为大家介绍矩阵对策的解法&#xff0c;包括图解法、方程组法和线性规划法三种经典方法。 01 图解法 本节首先介绍矩阵对策的图解法&#xff0c;…

Python贝叶斯分层模型专题|对环境健康、医学心梗患者、体育赛事数据空间异质性实证分析合集|附数据代码

全文链接&#xff1a;https://tecdat.cn/?p41267 在大数据时代&#xff0c;多水平数据结构广泛存在于环境健康、医学研究和体育赛事等领域。本专题合集聚焦贝叶斯分层模型&#xff08;Hierarchical Bayesian Model&#xff09;的创新应用&#xff0c;通过氡气污染数据与 季后…

NOI2015提高组.子串

题目 520. 子串 思路 设计状态表示 f [ i ] [ j ] [ k ] f[i][j][k] f[i][j][k]表示 a a a的前 i i i个字符, b b b的前 j j j个字符, 并且已经分割了 k k k个子串的所有方案, 将状态划分为包含第 i i i个字符和不包含第 i i i个字符, 不包含第 i i i个字符的状态是 f [ i…

医疗智能体通信整合-大模型训练中沟通优化策略研究

一、引言:医疗模型训练的沟通困境 1.1 医疗 AI 发展背景 在数智化浪潮的推动下,医疗 AI 正以前所未有的速度融入现代医疗体系。从智能影像诊断助力医生精准识别病灶,到基于大数据分析的个性化药物研发,医疗 AI 在提升医疗效率、改善医疗质量方面展现出巨大潜力。据相关数据…

存储管理(一)

目录 一、存储管理的功能 1.地址映射&#xff08;地址重定位&#xff09; 2.主存分配和回收 3.存储保护 4.主存扩充&#xff08;虚拟存储&#xff09; 二、程序的装入与链接 程序的装入&#xff1a; 程序的链接 三、连续分配方式 单一连续分配 固定分区分配 动态分…

SpringBoot学习笔记3.27

目录 实战篇第二课 1.注册参数的校验&#xff1a; 学习过程中遇到的问题&#xff1a; 1.什么是正则表达式 2.怎么自定义异常&#xff1f; 1. 创建全局异常处理类 2. 定义响应对象 3. 使用 ExceptionHandler 4. 设置响应状态码 5. 返回统一响应 6. 测试全局异常处理 …

基于springboot+vue的游戏账号交易系统的设计与实现

开发语言&#xff1a;Java框架&#xff1a;springbootJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#xff1a;…

小测验——合并多个网格文件调用相机参数进行适配

文章目录 一、前言1.1 对于rule1.2 对于ask、agent、edit1.3 对于没有notepad二、代码展示一、前言 1.1 对于rule 对于.cursorrules里面的文件内容,就是从提示词、项目简介、技术架构、目录结构、代码规范这几方面进行介绍 1.2 对于ask、agent、edit 切换模式在聊天框下方…

敏捷测试(Agile Testing)

敏捷测试&#xff08;Agile Testing&#xff09; 敏捷测试是在敏捷开发&#xff08;Agile Development&#xff09;环境下进行的软件测试方法&#xff0c;强调快速反馈、持续测试、团队协作&#xff0c;以确保软件质量贯穿整个开发周期。与传统瀑布模型不同&#xff0c;敏捷测…

FreeRTOS内核实现与应用学习之6——多优先级

在FreeRTOS中&#xff0c;数字优先级越小&#xff0c;逻辑优先级也越小&#xff1b;在任务创建时&#xff0c;会根据任务的优先级将任务插入就绪列表不同的位置。 相同优先级的任务插入就绪列表中的同一条链表中。 要想任务支持优先级&#xff0c;即只要实现在任务切换&#xf…

【C++篇】C++入门基础(二)

&#x1f4ac; 欢迎讨论&#xff1a;在阅读过程中有任何疑问&#xff0c;欢迎在评论区留言&#xff0c;我们一起交流学习&#xff01; &#x1f44d; 点赞、收藏与分享&#xff1a;如果你觉得这篇文章对你有帮助&#xff0c;记得点赞、收藏&#xff0c;并分享给更多对C感兴趣的…

Mysql架构之日志讲解:redo log,undo log,bin log 日志

一、buffer pool缓冲区 讲日志之前&#xff0c;我们要先认识一下buffer pool缓冲区。 mysql想完成数据的修改&#xff0c;会先从存储引擎层读取数据&#xff0c;把数据读取到服务层进行数据的修改&#xff0c;再通过存储引擎层把数据更新到数据库中。 mysql每次读取数据都会…

容器主机CPU使用率突增问题一则

关键词 LINUX、文件系统crontab 、mlocate根目录使用率 There are many things that can not be broken&#xff01; 如果觉得本文对你有帮助&#xff0c;欢迎点赞、收藏、评论&#xff01; 一、问题现象 业务一台容器服务器&#xff0c;近期经常收到cpu不定期抖动告警&#x…