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最优二叉树。 叶子结点(也称叶节点):指的是自己下面不再连接有节点的节点(即末端),称为叶子节点(又称为终…...
观成科技:隐蔽隧道工具Ligolo-ng加密流量分析
1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具,该工具基于TUN接口实现其功能,利用反向TCP/TLS连接建立一条隐蔽的通信信道,支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式,适应复杂网…...
Linux 文件类型,目录与路径,文件与目录管理
文件类型 后面的字符表示文件类型标志 普通文件:-(纯文本文件,二进制文件,数据格式文件) 如文本文件、图片、程序文件等。 目录文件:d(directory) 用来存放其他文件或子目录。 设备…...
第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明
AI 领域的快速发展正在催生一个新时代,智能代理(agents)不再是孤立的个体,而是能够像一个数字团队一样协作。然而,当前 AI 生态系统的碎片化阻碍了这一愿景的实现,导致了“AI 巴别塔问题”——不同代理之间…...
Rust 异步编程
Rust 异步编程 引言 Rust 是一种系统编程语言,以其高性能、安全性以及零成本抽象而著称。在多核处理器成为主流的今天,异步编程成为了一种提高应用性能、优化资源利用的有效手段。本文将深入探讨 Rust 异步编程的核心概念、常用库以及最佳实践。 异步编程基础 什么是异步…...
docker 部署发现spring.profiles.active 问题
报错: org.springframework.boot.context.config.InvalidConfigDataPropertyException: Property spring.profiles.active imported from location class path resource [application-test.yml] is invalid in a profile specific resource [origin: class path re…...
Go 语言并发编程基础:无缓冲与有缓冲通道
在上一章节中,我们了解了 Channel 的基本用法。本章将重点分析 Go 中通道的两种类型 —— 无缓冲通道与有缓冲通道,它们在并发编程中各具特点和应用场景。 一、通道的基本分类 类型定义形式特点无缓冲通道make(chan T)发送和接收都必须准备好࿰…...
搭建DNS域名解析服务器(正向解析资源文件)
正向解析资源文件 1)准备工作 服务端及客户端都关闭安全软件 [rootlocalhost ~]# systemctl stop firewalld [rootlocalhost ~]# setenforce 0 2)服务端安装软件:bind 1.配置yum源 [rootlocalhost ~]# cat /etc/yum.repos.d/base.repo [Base…...
LRU 缓存机制详解与实现(Java版) + 力扣解决
📌 LRU 缓存机制详解与实现(Java版) 一、📖 问题背景 在日常开发中,我们经常会使用 缓存(Cache) 来提升性能。但由于内存有限,缓存不可能无限增长,于是需要策略决定&am…...
群晖NAS如何在虚拟机创建飞牛NAS
套件中心下载安装Virtual Machine Manager 创建虚拟机 配置虚拟机 飞牛官网下载 https://iso.liveupdate.fnnas.com/x86_64/trim/fnos-0.9.2-863.iso 群晖NAS如何在虚拟机创建飞牛NAS - 个人信息分享...
MySQL:分区的基本使用
目录 一、什么是分区二、有什么作用三、分类四、创建分区五、删除分区 一、什么是分区 MySQL 分区(Partitioning)是一种将单张表的数据逻辑上拆分成多个物理部分的技术。这些物理部分(分区)可以独立存储、管理和优化,…...
