当前位置: 首页 > news >正文

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 运行截图

在这里插入图片描述

http://www.lryc.cn/news/5422.html

相关文章:

  • 微软Bing的AI人工只能对话体验名额申请教程
  • 怎么打造WhatsApp Team?SaleSmartly(ss客服)告诉你
  • IPV4地址的原理和配置
  • 软件测试面试准备——(一)Selenium(1)基础问题及自动化测试
  • AcWing 1230.K倍区间
  • kubernetes集群部署springcloud项目【AL】【未写完】
  • 各种音频接口比较
  • 软件测试面试理论(超详细)
  • c++学习笔记-二进制文件操作(哔站-黑马程序员c++教学视频)
  • 内网渗透(二十三)之Windows协议认证和密码抓取-Mimikatz介绍和各种模块使用方法
  • Nginx if的使用教程
  • 备考蓝桥杯【快速排序和归并排序】
  • Taro使用微信OCR插件无法调用onSuccess回调问题
  • 【Java】代码块的细节你搞懂了吗(基础知识七)
  • 设计模式C++实现12:抽象工厂模式
  • 目标检测论文阅读:GraphFPN算法笔记
  • 实测2023款哪吒U-II,智驾功能对女司机很友好
  • Python自动化测试【软件测试最全教程(附笔记、学习路线)】,看完即就业
  • 2023/2/13总结
  • webSock前端
  • AcWing 3956. 截断数组(每日一题)
  • Android 一体机研发之修改系统设置————屏幕亮度
  • C++通用算法
  • Springboot停机方式
  • Linux perf_event_open 简介
  • Java给定两组起止日期,求交集
  • 数组的复制与二维数组的用法
  • JS判断两个table数据是否完全相等(判断两个数组对象是否完全相等)
  • 关于小程序,你想知道的这些
  • WuThreat身份安全云-TVD每日漏洞情报-2023-02-13