基于springboot注解的shiro 授权及角色认证

news2024/12/25 0:06:33

目录

授权

后端接口服务注解

授权验证-没有角色无法访问

授权验证-获取角色进行验证 

授权验证-获取权限进行验证

授权验证-异常处理


授权

用户登录后,需要验证是否具有指定角色指定权限。Shiro也提供了方便的工具进行判 断。 这个工具就是Realm的doGetAuthorizationInfo方法进行判断。

触发权限判断的有两种 方式

(1) 在页面中通过shiro:****属性判断

(2) 在接口服务中通过注解@Requires****进行判断

后端接口服务注解

通过给接口服务方法添加注解可以实现权限校验,可以加在控制器方法上,也可以加 在业务方法上,一般加在控制器方法上。常用注解如下:

(1)@RequiresAuthentication

验证用户是否登录,等同于方法subject.isAuthenticated()

(2)@RequiresUser

验证用户是否被记忆: 登录认证成功subject.isAuthenticated()为true 登录后被记忆subject.isRemembered()为true

(3)@RequiresGuest

验证是否是一个guest的请求,是否是游客的请求 此时subject.getPrincipal()为null

(4)@RequiresRoles

验证subject是否有相应角色,有角色访问方法,没有则会抛出异常 AuthorizationException。 例如:

@RequiresRoles(“aRoleName”)

void someMethod();

只有subject有aRoleName角色才能访问方法someMethod()

(5)@RequiresPermissions

验证subject是否有相应权限,有权限访问方法,没有则会抛出异常 AuthorizationException。 例如:

@RequiresPermissions (“file:read”,”wite:aFile.txt”)

void someMethod();

subject必须同时含有file:read和wite:aFile.txt权限才能访问方法someMethod()

授权验证-没有角色无法访问

(1)添加 controller 方法,并添加验证角色注解 


//登录认证验证角色 
@RequiresRoles("admin") 
@GetMapping("userLoginRoles") 
@ResponseBody 
public String userLoginRoles() { 
 System.out.println("登录认证验证角色"); 
 return "验证角色成功"; 
}

(2)修改 main.html

<body> 
 <h1>Shiro 登录认证后主页面</h1> 
 <br> 
 登录用户为:<span th:text="${session.user}"></span> 
 <br> 
 <a href="/logout">登出</a> 
<br> 
 <a href="/myController/userLoginRoles">测试授权</a> 
</body>

(3)修改 MyRealm 方法

//自定义授权方法:获取当前登录用户权限信息,返回给 Shiro 用来进行授权对比 
@Override 
protected AuthorizationInfo 
doGetAuthorizationInfo(PrincipalCollection principalCollection) { 
 System.out.println("进入自定义授权方法"); 
 return null; 
} 

(4)运行测试

授权验证-获取角色进行验证 

(1)修改 MyRealm 方法 

//自定义授权方法:获取当前登录用户权限信息,返回给 Shiro 用来进行授权对比 
@Override 
protected AuthorizationInfo 
doGetAuthorizationInfo(PrincipalCollection principalCollection) { 
 System.out.println("进入自定义授权方法"); 
 //1 创建对象,存储当前登录的用户的权限和角色 
 SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); 
 //2 存储角色 
 info.addRole("admin"); 
 //返回 
 return info; 
} 

(2)运行测试

 (3)确认库表

CREATE TABLE `role` ( 
 `id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '编号', 
 `name` VARCHAR(30) DEFAULT NULL COMMENT '角色名', 
 `desc` VARCHAR(50) DEFAULT NULL COMMENT '描述', 
 `realname` VARCHAR(20) DEFAULT NULL COMMENT '角色显示名', 
 PRIMARY KEY (`id`) 
) ENGINE=INNODB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COMMENT='角色表'; 

CREATE TABLE `role_user` ( 
 `id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '编号', 
 `uid` BIGINT(20) DEFAULT NULL COMMENT '用户 id', 
 `rid` BIGINT(20) DEFAULT NULL COMMENT '角色 id', 
 PRIMARY KEY (`id`) 
) ENGINE=INNODB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COMMENT='角色用户映射表'; 

 (4)查询 sql 根据用户名查询对应角色信息

SELECT NAME FROM role WHERE id IN (SELECT rid FROM role_user WHERE uid=(SELECT id FROM USER WHERE NAME='张三'));

 (5)mapper 方法

@Repository 
public interface UserMapper extends BaseMapper<User> { 
 @Select("SELECT NAME FROM role WHERE id IN (SELECT rid FROM 
role_user WHERE uid=(SELECT id FROM USER WHERE NAME=#{principal}))") 
 List<String> getUserRoleInfoMapper(@Param("principal") String 
principal); 
}

(6)service 实现

//获取用户的角色信息 
@Override 
public List<String> getUserRoleInfo(String principal) { 
 return userMapper.getUserRoleInfoMapper(principal); 
} 

 (7)MyRealm 方法改造

//自定义授权方法:获取当前登录用户权限信息,返回给 Shiro 用来进行授权对比 
@Override 
protected AuthorizationInfo 
doGetAuthorizationInfo(PrincipalCollection principalCollection) { 
 System.out.println("进入自定义授权方法"); 
 //获取当前用户身份信息 
 String principal = 
principalCollection.getPrimaryPrincipal().toString(); 
 //调用接口方法获取用户的角色信息 
 List<String> roles = userService.getUserRoleInfo(principal); 
 System.out.println("当前用户角色信息:"+roles); 
 //创建对象,存储当前登录的用户的权限和角色 
 SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); 
 //存储角色 
 info.addRoles(roles); 
 //返回 
 return info; 
} 

(8)启动登录测试

授权验证-获取权限进行验证

获取权限验证和获取角色相类似

(1)确认库表

CREATE TABLE `permissions` ( 
 `id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '编号', 
 `name` VARCHAR(30) DEFAULT NULL COMMENT '权限名', 
 `info` VARCHAR(30) DEFAULT NULL COMMENT '权限信息', 
 `desc` VARCHAR(50) DEFAULT NULL COMMENT '描述', 
 PRIMARY KEY (`id`) 
) ENGINE=INNODB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COMMENT='权限表';

CREATE TABLE `role_ps` ( 
 `id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '编号', 
 `rid` BIGINT(20) DEFAULT NULL COMMENT '角色 id', 
 `pid` BIGINT(20) DEFAULT NULL COMMENT '权限 id', 
 PRIMARY KEY (`id`) 
) ENGINE=INNODB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COMMENT='角色权限映射表`

 

(2)查询 sql 根据角色名查询对应权限信息

SELECT info FROM permissions WHERE id IN (SELECT pid FROM role_ps WHERE rid IN (SELECT id FROM role WHERE NAME IN('admin','userMag')));

(3)mapper 方法

@Select({ 
 "<script>", 
 "select info FROM permissions WHERE id IN ", 
 "(SELECT pid FROM role_ps WHERE rid IN (", 
 "SELECT id FROM role WHERE NAME IN ", 
 "<foreach collection='roles' item='name' open='(' 
separator=',' close=')'>", 
 "#{name}", 
 "</foreach>", 
 "))", 
 "</script>" 
}) 
List<String> getUserPermissionInfoMapper(@Param("roles")List<String> 
roles);

 (4)service 实现

//获取用户角色的权限信息 
@Override 
public List<String> getUserPermissionInfo(List<String> roles) { 
 return userMapper.getUserPermissionInfoMapper(roles); 
}

(5)MyRealm 方法改造

//自定义授权方法:获取当前登录用户权限信息,返回给 Shiro 用来进行授权对比 
@Override 
protected AuthorizationInfo 
doGetAuthorizationInfo(PrincipalCollection principalCollection) { 
 System.out.println("进入自定义授权方法"); 
 //获取当前用户身份信息 
 String principal = 
principalCollection.getPrimaryPrincipal().toString(); 
 //调用接口方法获取用户的角色信息 
 List<String> roles = userService.getUserRoleInfo(principal); 
 System.out.println("当前用户角色信息:"+roles); 
 //调用接口方法获取用户角色的权限信息 
 List<String> permissions = 

userService.getUserPermissionInfo(roles); 
 System.out.println("当前用户权限信息:"+permissions); 
 //创建对象,存储当前登录的用户的权限和角色 
 SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); 
 //存储角色 
 info.addRoles(roles); 
 //存储权限信息 
 info.addStringPermissions(permissions); 
 //返回 
 return info; 
}

(6)添加 controller 方法

//登录认证验证权限 
@RequiresPermissions("user:delete") 
@GetMapping("userPermissions") 
@ResponseBody 
public String userLoginPermissions() { 
 System.out.println("登录认证验证权限"); 
 return "验证权限成功"; 
}

(7)改造 main.html

<body> 
 <h1>Shiro 登录认证后主页面</h1> 
 <br> 
 登录用户为:<span th:text="${session.user}"></span> 
 <br> 
 <a href="/logout">登出</a> 
 <br> 
 <a href="/myController/userLoginRoles">测试授权-角色验证</a> 
 <br> 
 <a href="/myController/userPermissions">测试授权-权限验证</a> 
</body> 

 (8)启动登录测试

授权验证-异常处理

(1)创建认证异常处理类,使用@ControllerAdvice 加@ExceptionHandler 实现特殊异 常处理。

@ControllerAdvice 
public class PermissionsException { 
 @ResponseBody 
 @ExceptionHandler(UnauthorizedException.class) 
 public String unauthorizedException(Exception ex){ 
 return "无权限"; 
 } 
 
 @ResponseBody 
 @ExceptionHandler(AuthorizationException.class) 
 public String authorizationException(Exception ex){ 
 return "权限认证失败"; 
 } 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

华为OD机试真题B卷 Java 实现【狼羊过河】,附详细解题思路

一、题目描述 一农夫带着m只羊&#xff0c;n只狼过河&#xff0c;农夫有一条可载x只狼/羊的船&#xff1b;农夫在时或者羊的数量大于狼时&#xff0c;狼不会攻击羊&#xff1b; 农夫在不损失羊的情况下&#xff0c;运输几次可以完成运输&#xff1f; 返程不计入次数。 二、…

K8s容器运行环境安全加固

K8s容器运行环境安全加固 目录 文章目录 K8s容器运行环境安全加固目录1、最小特权原则&#xff08;POLP&#xff09;2、AppArmor限制容器对资源访问3、Seccomp 限制容器进程系统调用关于我最后 1、最小特权原则&#xff08;POLP&#xff09; **最小特权原则 (Principle of lea…

graalvm把java编译为c/c++能够使用的动态库(dll/so)

graalvm把java编译为c/c能够使用的动态库(dll/so) 1.安装graalvm oracle官方企业版 github的openjdk版本 1.1 下载对应系统版本&#xff0c;配置环境变量 本人环境 1. win10 openjdk 17.0.5 2022-10-18 OpenJDK Runtime Environment GraalVM CE 22.3.0 (build 17.0.58-jv…

chatgpt赋能python:Python中的None值如何去掉?

Python中的None值如何去掉&#xff1f; Python是一种具有高度灵活性和可读性的编程语言&#xff0c;它有许多强大的功能&#xff0c;令许多开发人员喜欢使用它。然而&#xff0c;可能会遇到延迟或者None值的情况&#xff0c;这时需要我们找到正确的方法去除它们。 None值是什…

C#,码海拾贝(27)——求解“对称方程组”的“分解法”之C#源代码,《C#数值计算算法编程》源代码升级改进版

using System; namespace Zhou.CSharp.Algorithm { /// <summary> /// 求解线性方程组的类 LEquations /// 原作 周长发 /// 改编 深度混淆 /// </summary> public static partial class LEquations { /// <summary> /…

happens-before规则

happens-before背景由来 happens-before的概念最初由Leslie Lamport在其一篇影响深远的论文&#xff08;《Time&#xff0c;Clocks and the Ordering of Events in a Distributed System》&#xff09;中提出。Leslie Lamport使用 happens-before 来定义分布式系统中事件之间…

【利用AI让知识体系化】7种结构型模式

文章目录 结构型模式简介适配器模式装饰器模式代理模式外观模式桥接模式组合模式享元模式 结构型模式 简介 在设计模式中&#xff0c;结构型模式用于描述如何将对象和类组装成较大的结构&#xff0c;并灵活地处理对象之间的关系。 结构型模式包括以下几种&#xff1a; 适配器…

驱动开发——嵌入式(驱动)软开基础(十)

1. 64位的计算机有哪些优点&#xff1f; &#xff08;1&#xff09;可以进行更大范围的整数计算。 &#xff08;2&#xff09;可以支持更大的内存&#xff0c;虚拟内存空间大小一般为2^48&#xff08;256TB&#xff09;。64位的Linux一般使用48位表示虚拟内存空间地址&#x…

esp8266 OTA远程无线升级

第一步、编译生成.bin升级固件 本教程需要用到 arduino IDE的esp8266开发环境,关于arduino IDE 的ESP8266环境配置可参考:环境配置: 点击跳转 如果已安装好esp8266 开发环境,继续: 使用arduino IDE软件,打开随便一个需要升级的程序,点击「项目」-「导出已编译的二进制…

【Bug 全解决】 Java、Spring boot 后端项目 Bug 总结

Bug 收集与总结 本文记录的是 SpringBoot 后端项目使用和运行代码时所遇到的各种问题&#xff0c;全部都已解决&#xff0c;欢迎在评论区补充你遇到的 Bug 哦&#xff01;仅以本文记录学习社区项目时&#xff0c;所遇到的奇奇怪怪的 bug&#xff0c;以及一些很愚蠢的错误&…

Golang每日一练(leetDay0080) 矩形面积、翻转二叉树

目录 223. 矩形面积 Rectangle Area &#x1f31f;&#x1f31f; 226. 翻转二叉树 Invert Binary Tree &#x1f31f; &#x1f31f; 每日一练刷题专栏 &#x1f31f; Rust每日一练 专栏 Golang每日一练 专栏 Python每日一练 专栏 C/C每日一练 专栏 Java每日一练 专栏…

RPC原理与实现

rpc叫做远程过程调用&#xff0c;是指一台机器上的服务通过通信协议调用网络中另一台机器上的程序&#xff0c;并拿到结果。 1、基本流程 基本流程为&#xff1a; 客户端程序通过Client Stub调度rpc函数Client Stub将调用方法、参数按照通信协议序列化成网络二进制数据&#…

koa2中HTTP错误处理

HTTP错误 访问 Web 服务器或应用程序时&#xff0c;服务器收到的每个 HTTP 请求都会以 HTTP 状态代码进行响应。 HTTP 状态代码是三位数代码&#xff0c;分为五个不同的类别。 状态代码的类别可以通过它的第一个数字快速识别&#xff1a; 1xx&#xff1a;信息2xx&#xff1a…

“大娘,你听说过ChatGPT吗?”,“你说的那个什么鸡皮蹄,我这饼里加不了!”

最近看到一个有意思的段子&#xff0c;大概意思是&#xff1a; 年轻人去买煎饼&#xff0c;问摊煎饼的大娘知不知道什么是ChatGPT。 大娘摇了摇头&#xff1a;“你说的那个什么鸡皮蹄&#xff0c;我这饼里加不了”。 年轻人尝试跟大娘解释ChatGPT是什么东西&#xff0c;大娘…

快速上手kettle(二)小试牛刀

快速上手kettle二 小试牛刀 一 、前言二 、两个小目标三、 kettle核心概念介绍3.1 转换3.1.1 步骤(Step)3.1.2 跳&#xff08;Hop&#xff09;3.1.3 元素据3.1.4 数据类型3.1.5 并发执行 3.2 作业 四、实践操作4.1 案例1 将csv文件转换成excel文件4.1.1 在kettle中新建一个转换…

在Node.js中接受来自命令行的输入

目录 1、简介 2、readlineSync 3、列表选择一个项目&#xff1a; 4、类似滑块范围的UI: 1、简介 如何制作一个Node.js CLI程序使用内置的readline Node.js模块进行交互 如何制作一个节点js CLI程序交互&#xff1f; Node.js 从版本7起开始提供了readline模块来执行以下操…

styleFlow数学推导

如果 w 和 z 的变换是线性的&#xff0c;即 w az b&#xff0c;那么 dw a dz&#xff0c; 所以 p(w) dw p(z) dz 等价于 p(w) a p(z) 即 w 的概率密度函数是 z 的概率密度函数乘以一个常数因子。 如果 w 和 z 是通过一个可逆的函数 ϕ 相互转换的&#xff0c;即 w ϕ(…

5.29今日黄金最新行情走势分析及多空交易策略

近期有哪些消息面影响黄金走势&#xff1f;今日黄金多空该如何研判&#xff1f; ​黄金消息面解析&#xff1a;上周五(5月26日)美市尾盘&#xff0c;现货黄金收报1946.01美元/盎司&#xff0c;上升4.76美元或0.25%&#xff0c;日内最高触及1957.31美元/盎司&#xff0c;最低触…

1.3 eBPF的工作原理初探 --- 更新中

写在前面 上一节提到过,eBPF程序是面向BPF体系结构指令集编写的,它并不直接运行在Linux内核中,我们可以理解为它是运行在eBPF虚拟机,由eBPF虚拟机来执行eBPF字节码,就像java运行在jvm一样。 我们用一张原理图来看下eBPF程序的编译,加载,验证,钩子,映射等结点。 如上是…

Java学习路线(16)——异常

一、异常 1、概念&#xff1a; 程序在“编译”或“执行”时可能出现的问题。&#xff08;语法错误不算异常&#xff09; 2、常见的异常 数组索引越界空指针日期格式化… 3、作用&#xff1a; 触发异常后&#xff0c;如果没有提前处理&#xff0c;JVM将终止&#xff0c;提高…