Spring Boot学习篇(十三)
Spring Boot学习篇(十三)
shiro安全框架使用篇(五)
1 准备工作
1.1 在SysUserMapper.xml中书写自定义标签
<select id="findRoles" resultType="string">select name from sys_role where id = (select roleid from sys_user_role where userid = (SELECT id FROM `sys_user` where username = #{username}))
</select>
<select id="findPerms" resultType="string">select name from sys_permission where id in(select perid from sys_role_permission where roleid in(select roleid from sys_user_role where userid in(SELECT id FROM `sys_user` where username =#{username})))
</select>
1.2 SysUserMapper接口书写自定义标签所对应的方法
//根据用户名查询角色
List<String> findRoles(String username);
//根据用户名查询权限
List<String> findPerms(String username);
1.3 login.html界面
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><h2 th:if="${msg!=null}" th:text="${msg}"></h2><form action="/users/login" method="post"><!--需要与控制器保持一致-->用户名:<input type="text" name="yhm">密码:<input type="password" name="mm">记住我: <input type="checkbox" name="jzw"><button>登录</button></form>
</body>
</html>
1.4 index.html界面
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>主页<a href="/zhuxiao">注销</a><a href="/songs/find">查询商品</a><a href="/songs/update">更改商品</a><a href="/songs/insert">添加商品</a><a href="/songs/delete">删除商品</a>
</body>
</html>
1.5 qx.html界面
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><h1>你没有该访问权限</h1><a href="/index.html">点击进入主页</a>
</body>
</html>
1.6 SongsController类
package com.zlz.controller;import com.zlz.entity.Songs;
import com.zlz.service.ISongsService;
import org.apache.shiro.authz.annotation.Logical;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.apache.shiro.authz.annotation.RequiresUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ResponseBody;import java.util.List;/*** <p>* 前端控制器* </p>** @author zlz* @since 2023-02-04*/
//跨域的问题 1.协议不同 2.地址不同 3.端口不同 三者满足其一,就是跨域
//(origins = "*") origins仅允许指定域名访问 (origins = "http://127.0.0.1:8848")
@CrossOrigin
@Controller
@RequestMapping("/songs")
public class SongsController {@AutowiredISongsService iSongsService;@RequestMapping("select")@ResponseBodypublic List<Songs> s(){return iSongsService.list();}@RequestMapping("find")public String a(){System.out.println("查询数据");return "index";}@RequestMapping("delete")////角色,需要自定义异常@RequiresRoles(value = {"经理","组长"},logical = Logical.OR)//判断是否具有权限的
// @RequiresPermissions()public String b(){System.out.println("删除数据");return "index";}@RequiresUser@RequestMapping("update")public String c(){System.out.println("修改数据");return "index";}@RequestMapping("insert")public String d(){System.out.println("添加数据");return "index";}}
2.操作授权(全满足)
2.1 在MySqlRealm类里面(继承了AuthorizingRealm抽象类)书写授权方法的内容
@Resource
SysUserMapper sysUserMapper;
//授权方法
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection p) {//注意看方法的返回值,一般是返回方法返回值类型所对应的实现类(Simple开头+方法返回值类型)//①得到当前登录的用户名String yhm =(String)p.getPrimaryPrincipal();//②查询到该用户的角色和权限List<String> roles = sysUserMapper.findRoles(yhm);List<String> perms = sysUserMapper.findPerms(yhm);//③ 控制台打印 方便查看效果System.out.println(yhm+"具有权限"+roles);System.out.println(yhm+"具有角色"+perms);//④授权并返回SimpleAuthorizationInfo sm=new SimpleAuthorizationInfo();sm.addRoles(roles);sm.addStringPermissions(perms);return sm;
}
2.2 在ShiroConfig类的factoryBean方法中配置控制器过滤
//默认是roles[角色名1,角色名2...角色名n],因为底层用的是hasAllRoles方法,因此是必须含有全部权限
//下面代码表示经理和组长的权限都要满足才可以进行删除
map.put("/songs/delete","user,roles[经理,组长]");
2.3 在ShiroConfig类中的factoryBean方法配置没有权限时的跳转地址
//检测到没有权限时的地址
sb.setUnauthorizedUrl("/qx.html");
2.4 设置没有权限时跳转的页面(templates目录下)
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><h1>你没有该访问权限</h1><a href="/index.html">点击进入主页</a>
</body>
</html>
2.5 测试
2.5.1 使用admin用户(具有经理权限)登录后并点击删除商品进入如下界面

2.5.2 使用aaa用户(具有组长权限)登录后并点击删除商品进入如下界面

3.操作授权(满足其中之一)
3.1 自定义角色过滤器类MyRolesFilter(继承RolesAuthorizationFilter类)
package com.zlz.filter;import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.CollectionUtils;
import org.apache.shiro.web.filter.authz.RolesAuthorizationFilter;import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.io.IOException;
import java.util.Set;/*** 自定义角色过滤器*/
public class MyRolesFilter extends RolesAuthorizationFilter {@Overridepublic boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws IOException {Subject subject = this.getSubject(request, response);String[] rolesArray = (String[])mappedValue;if (rolesArray != null && rolesArray.length != 0) {Set<String> roles = CollectionUtils.asSet(rolesArray);boolean b=false;for (String role : roles) {//满足其中之一就返回,hasRole满足条件就为true,if(subject.hasRole(role)){b=true;break;}}return b;} else {return true;}}
}
3.2 核心代码(在ShiroConfig类中factoryBean方法中)
/**
* 自定义过滤器 换个名字好点 sb是ShiroFilterFactoryBean类型的对象
*/
Map<String, Filter> myFilter=new HashMap<>();
myFilter.put("myroles",new MyRolesFilter());
sb.setFilters(myFilter);
//设置删除商品需要经理或者组长其一的权限
map.put("/songs/delete","user,myroles[经理,组长]");
3.3 完整的ShiroConfig类代码
package com.zlz.config;import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import com.zlz.filter.MyRolesFilter;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.filter.authc.LogoutFilter;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.crazycake.shiro.RedisCacheManager;
import org.crazycake.shiro.RedisManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;import javax.servlet.Filter;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;@Configuration
public class ShiroConfig {//shiro标签库@Beanpublic ShiroDialect sd(){return new ShiroDialect();}//配置安全管理器 shiro核心配置类@Beanpublic DefaultWebSecurityManager securityManager(){DefaultWebSecurityManager dms=new DefaultWebSecurityManager();//设置域(查询数据库dao类) 查哪里的数据库设置dms.setRealm(realm());//设置会话管理器dms.setSessionManager(new DefaultWebSessionManager());//设置记住我管理器dms.setRememberMeManager(ck());return dms;}@Beanpublic Realm realm(){MysqlRealm r=new MysqlRealm();//设置密码加密 登录是加密比对HashedCredentialsMatcher hsm = new HashedCredentialsMatcher();hsm.setHashAlgorithmName("sha-256");hsm.setHashIterations(100);r.setCredentialsMatcher(hsm);return r;}//shiro过滤器(核心)@Bean("shiroFilterFactoryBean")public ShiroFilterFactoryBean factoryBean(){ShiroFilterFactoryBean sb=new ShiroFilterFactoryBean();//设置安全管理器sb.setSecurityManager(securityManager());/*基本设置*///检测到没有登录的地址sb.setLoginUrl("/login.html");//检测到没有权限时的地址(这里是一种设置没有权限时候跳转的地址)sb.setUnauthorizedUrl("/qx.html");/*** 自定义过滤器 换个名字好点 sb是ShiroFilterFactoryBean类型的对象是通过map集合设置进去的*/Map<String, Filter> myFilter=new HashMap<>();myFilter.put("myroles",new MyRolesFilter());sb.setFilters(myFilter);//控制器过滤设置 拦截有顺序///*** anon 允许匿名访问 无需登录* user 需要登录后才能访问* roles 需要具有所有的角色* perms 需要具有所有的权限* logout 注销过滤器* authc 不包含记住我 需要登录*/Map<String,String> map=new LinkedHashMap<>();map.put("/*.html", "anon");//注销流程 自己清空sessionmap.put("/zhuxiao", "logout");map.put("/songs/find","anon");//myroles就是和之前定义的key值保持一致map.put("/songs/delete","user,myroles[经理,组长]");//放行写上面 拦截写下面sb.setFilterChainDefinitionMap (map);return sb;}@Beanpublic CookieRememberMeManager ck(){CookieRememberMeManager c=new CookieRememberMeManager();SimpleCookie sc=new SimpleCookie();sc.setHttpOnly(true);//防止js读取cookiesc.setMaxAge(60);//设置cookie时长sc.setName("zlz");c.setCookie(sc);return c;}
}
3.3 测试
3.3.1 组长权限(用户名为aaa)
a 点击删除按钮后跳转的界面

b 点击删除按钮后的idea控制台界面

3.3.2 管理员权限(用户名为admin)
a 点击删除按钮后跳转的界面

b 点击删除按钮后的idea控制台界面

4 设置注销后跳转的地址
4.1 核心代码
//Map<String, Filter> myFilter=new HashMap<>();
LogoutFilter logoutFilter = new LogoutFilter();
logoutFilter.setRedirectUrl("/index.html");//修改注销后的跳转地址,如果没有设置默认跳转的是login.html界面myFilter.put("logout",logoutFilter);
4.2 运行截图

相关文章:
Spring Boot学习篇(十三)
Spring Boot学习篇(十三) shiro安全框架使用篇(五) 1 准备工作 1.1 在SysUserMapper.xml中书写自定义标签 <select id"findRoles" resultType"string">select name from sys_role where id (select roleid from sys_user_role where userid (S…...
微软Bing的AI人工只能对话体验名额申请教程
微软Bing 免费体验名额申请教程流程ChatGPT这东西可太过火了。国外国内,圈里圈外都是人声鼎沸。微软,谷歌,百度这些大佬纷纷出手。连看个同花顺都有GPT概念了,搞技术,做生意的看来都盯上了 流程 下面就讲一下如何申…...
怎么打造WhatsApp Team?SaleSmartly(ss客服)告诉你
关键词:WhatsApp Team SaleSmartly(ss客服) 您是否正在寻找一种让您的团队能够在 WhatsApp协作消息传递的解决方案?拥有了 WhatsApp Team,不仅效率提升,还可以在智能聊天工具中比如SaleSmartly(ss客服&…...
IPV4地址的原理和配置
第三章:IP地址的配置 IPv4(Internet Protocol Version 4)协议族是TCP/IP协议族中最为核心的协议族。它工作在TCP/IP协议栈的网络层,该层与OSI参考模型的网络层相对应。网络层提供了无连接数据传输服务,即网络在发送分…...
软件测试面试准备——(一)Selenium(1)基础问题及自动化测试
滴滴面试:1. 自己负责哪部分功能?农餐对接系统分为了两大子系统,一个是个人订餐系统,二是餐馆、个人与农产品供应商进行农产品交易系统。我主要负责组织测试人员对该系统进行测试。我们测试分为两个阶段:一、功能测试阶…...
AcWing 1230.K倍区间
AcWing 1230. K倍区间 题目描述 给定一个长度为 NNN 的数列,A1,A2,…ANA_1, A_2, … A_NA1,A2,…AN ,如果其中一段连续的子序列 Ai,Ai1,…AjA_i, A_{i1}, … A_jAi,Ai1,…Aj 之和是 KKK 的倍数,我们就称这个区间 [i,j][i,j][i,…...
kubernetes集群部署springcloud项目【AL】【未写完】
kubernetes集群部署springcloud项目【AL】 (先手工做,非自动化) #环境: 192.168.73.138 master 192.168.73.139 node1 192.168.73.140 node2 192.168.73.137 harbor、mysqlgit clone https://github.com/lizhenliang/simple-…...
各种音频接口比较
时间 参考:https://www.bilibili.com/video/BV1SL4y1q7GZ/?spm_id_from333.337.search-card.all.click&vd_source00bd76f9d6dc090461cddd9f0deb2d51, https://blog.csdn.net/weixin_43794311/article/details/128941346 接口名字时间公司支持格式…...
软件测试面试理论(超详细)
【面试理论知识】1、你的测试职业发展是什么? 测试经验越多,测试能力越高。所以我的职业发展是需要时间积累的,一步步向着高级测试工程师奔去。而且我也有初步的职业规划,前3年积累测试经验,按如何做好测试工程师的要点去要求自己…...
c++学习笔记-二进制文件操作(哔站-黑马程序员c++教学视频)
一、基本概念 以二进制的方式对文件进行读写操作 打开方式指定为 ios::binary 优点:可以写入自己定义的数据类型 1、写文件 二进制方式写文件:流对象调用成员write 函数原型:ostream& write(const char * buffer,int len);参数解释…...
内网渗透(二十三)之Windows协议认证和密码抓取-Mimikatz介绍和各种模块使用方法
系列文章第一章节之基础知识篇 内网渗透(一)之基础知识-内网渗透介绍和概述 内网渗透(二)之基础知识-工作组介绍 内网渗透(三)之基础知识-域环境的介绍和优点 内网渗透(四)之基础知识-搭建域环境 内网渗透(五)之基础知识-Active Directory活动目录介绍和使用 内网渗透(六)之基…...
Nginx if的使用教程
if指令该指令用来支持条件判断,并根据条件判断结果选择不同的Nginx配置。语法if (condition){...}默认值—位置server、locationcondition为判定条件,可以支持以下写法:1. 变量名。如果变量名对应的值为空字符串或"0",i…...
备考蓝桥杯【快速排序和归并排序】
🌹作者:云小逸 📝个人主页:云小逸的主页 📝Github:云小逸的Github 🤟motto:要敢于一个人默默的面对自己,强大自己才是核心。不要等到什么都没有了,才下定决心去做。种一颗树,最好的时间是十年前…...
Taro使用微信OCR插件无法调用onSuccess回调问题
Taro使用微信插件无法调用onSuccess回调问题小程序后台添加插件在开放社区购买相应的套餐详细步骤1.在app.config.js中添加如下代码2.在页面的page.config.js添加插件3.使用ocr-navigator识别身份证小程序后台添加插件 在开放社区购买相应的套餐 购买地址 详细步骤 1.在app.…...
【Java】代码块的细节你搞懂了吗(基础知识七)
希望像唠嗑一样,one step one futher。 目录 (1)代码块的应用场景 (2)代码块的细节 1.static 代码块只加载一次 2.当调用类的静态成员时,类会加载 3. 使用类的静态成员时,static代码块会被执…...
设计模式C++实现12:抽象工厂模式
参考大话设计模式; 详细内容参见大话设计模式一书第十五章,该书使用C#实现,本实验通过C语言实现。 抽象工厂模式(Abstract Factory),提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们…...
目标检测论文阅读:GraphFPN算法笔记
标题:GraphFPN: Graph Feature Pyramid Network for Object Detection 会议:ICCV2021 论文地址:https://ieeexplore.ieee.org/document/9710561/ Abstract 特征金字塔已经被证明在需要多尺度特征的图像理解任务中是强大的。SOTA的多尺度特征…...
实测2023款哪吒U-II,智驾功能对女司机很友好
最近,我们受邀试驾了2023款哪吒U-II。这是一款A级新能源SUV,是哪吒U的改款车型。哪吒U系列自2020年3月上市到2023年1月,累计销售数量达76688台,也因此被称为15万级智能天花板。2023款哪吒U-II的一大亮点是:针对以往哪吒…...
Python自动化测试【软件测试最全教程(附笔记、学习路线)】,看完即就业
最近看到很多粉丝在后台私信我,叫我做一期Python自动化测试的教程,其实关于这个问题,我也早就在着手准备了,我录制了一整套完整的Python自动化测试的教程,上传到网盘里了,大家有兴趣的可以去文末交流群免费…...
2023/2/13总结
今天主要学习了哈夫曼树。 哈夫曼树 哈夫曼树是二叉树的一种,它是一种WPL最优二叉树。 叶子结点(也称叶节点):指的是自己下面不再连接有节点的节点(即末端),称为叶子节点(又称为终…...
变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析
一、变量声明设计:let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性,这种设计体现了语言的核心哲学。以下是深度解析: 1.1 设计理念剖析 安全优先原则:默认不可变强制开发者明确声明意图 let x 5; …...
【网络】每天掌握一个Linux命令 - iftop
在Linux系统中,iftop是网络管理的得力助手,能实时监控网络流量、连接情况等,帮助排查网络异常。接下来从多方面详细介绍它。 目录 【网络】每天掌握一个Linux命令 - iftop工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景…...
LeetCode - 394. 字符串解码
题目 394. 字符串解码 - 力扣(LeetCode) 思路 使用两个栈:一个存储重复次数,一个存储字符串 遍历输入字符串: 数字处理:遇到数字时,累积计算重复次数左括号处理:保存当前状态&a…...
Java-41 深入浅出 Spring - 声明式事务的支持 事务配置 XML模式 XML+注解模式
点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...
数据库分批入库
今天在工作中,遇到一个问题,就是分批查询的时候,由于批次过大导致出现了一些问题,一下是问题描述和解决方案: 示例: // 假设已有数据列表 dataList 和 PreparedStatement pstmt int batchSize 1000; // …...
在WSL2的Ubuntu镜像中安装Docker
Docker官网链接: https://docs.docker.com/engine/install/ubuntu/ 1、运行以下命令卸载所有冲突的软件包: for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done2、设置Docker…...
鸿蒙DevEco Studio HarmonyOS 5跑酷小游戏实现指南
1. 项目概述 本跑酷小游戏基于鸿蒙HarmonyOS 5开发,使用DevEco Studio作为开发工具,采用Java语言实现,包含角色控制、障碍物生成和分数计算系统。 2. 项目结构 /src/main/java/com/example/runner/├── MainAbilitySlice.java // 主界…...
NXP S32K146 T-Box 携手 SD NAND(贴片式TF卡):驱动汽车智能革新的黄金组合
在汽车智能化的汹涌浪潮中,车辆不再仅仅是传统的交通工具,而是逐步演变为高度智能的移动终端。这一转变的核心支撑,来自于车内关键技术的深度融合与协同创新。车载远程信息处理盒(T-Box)方案:NXP S32K146 与…...
C#学习第29天:表达式树(Expression Trees)
目录 什么是表达式树? 核心概念 1.表达式树的构建 2. 表达式树与Lambda表达式 3.解析和访问表达式树 4.动态条件查询 表达式树的优势 1.动态构建查询 2.LINQ 提供程序支持: 3.性能优化 4.元数据处理 5.代码转换和重写 适用场景 代码复杂性…...
MySQL 8.0 事务全面讲解
以下是一个结合两次回答的 MySQL 8.0 事务全面讲解,涵盖了事务的核心概念、操作示例、失败回滚、隔离级别、事务性 DDL 和 XA 事务等内容,并修正了查看隔离级别的命令。 MySQL 8.0 事务全面讲解 一、事务的核心概念(ACID) 事务是…...
