前言:上一篇文章讲述了如何使用角色url进行粗粒度验证。地址:https://blog.csdn.net/xcc_2269861428/article/details/95768417

这篇说下如何使用perms进行细粒度验证,已经我写代码过程中碰见的坑。

看下角色界面

我在数据库中分别为2个就是设置了perms权限

用户界面

图中可以看出,xcc是没有角色管理权限的,所以不能对角色进行增删改查。

当我用xcc这个用户点击角色部分按钮就会报错。

为xcc分配角色管理权限

再次点击角色部分的按钮,是可以的

为什么要使用perms进行验证呢,因为他很细粒度化,他可以帮助我们精确到每个按钮,并且不需要太多的代码就可以实现。

看下controller部分的代码

package com.waysoft.modules.business.integrate.user.controller;import java.util.ArrayList;
import java.util.List;import javax.servlet.http.HttpServletRequest;import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authz.annotation.Logical;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;import com.waysoft.common.ResponseData;
import com.waysoft.global.model.Menu;
import com.waysoft.global.model.Role;
import com.waysoft.global.model.User;
import com.waysoft.modules.business.integrate.user.service.UserService;@Controller
@RequestMapping("/user")
public class UserController {@Autowiredprivate UserService userService;/*** @Description 获取数据* @param request* @return ResponseData*/@RequestMapping(value="login", method = RequestMethod.POST, produces = "application/json;charset=UTF-8")@ResponseBodypublic ResponseData save(HttpServletRequest request,User user){ResponseData responseData=new ResponseData();try {responseData = userService.login(user);}catch(Exception e){responseData.setStatus(1);responseData.setMsg("登录失败");}return  responseData;}/*** 退出登录* @param request* @param user* @return*/@RequestMapping(value="login_out", method = RequestMethod.GET, produces = "application/json;charset=UTF-8")@ResponseBodypublic ResponseData login_out(HttpServletRequest request,User user){ResponseData responseData=new ResponseData();try {Subject subject = SecurityUtils.getSubject();subject.logout();responseData.setStatus(0);responseData.setMsg("退出成功");}catch(Exception e){responseData.setStatus(1);responseData.setMsg("退出失败");}return  responseData;}/*** 添加用户* @param request* @param user* @return*/@RequiresPermissions(value={"user:add"})@RequestMapping(value="insertUser", method = RequestMethod.POST, produces = "application/json;charset=UTF-8")@ResponseBodypublic ResponseData insertUser(HttpServletRequest request,User user){ResponseData responseData=new ResponseData();try {userService.insertUser(user);responseData.setStatus(0);responseData.setMsg("添加成功");}catch(Exception e){responseData.setStatus(1);responseData.setMsg("添加失败");}return  responseData;}/*** 回显用户* @param request* @param id* @return*/@RequestMapping(value="getUser/{id}", method = RequestMethod.GET, produces = "application/json;charset=UTF-8")@RequiresPermissions(value={"user:get"}, logical = Logical.OR)@ResponseBodypublic ResponseData getUser(HttpServletRequest request,@PathVariable("id") String id){ResponseData responseData=new ResponseData();try {User user = userService.getUserById(id);responseData.setStatus(0);responseData.setData(user);responseData.setMsg("获取成功");}catch(Exception e){responseData.setStatus(1);responseData.setMsg("获取失败");}return  responseData;}/*** 修改用户* @param request* @param user* @return*/@RequiresPermissions(value={"user:update"})@RequestMapping(value="updateUser", method = RequestMethod.POST, produces = "application/json;charset=UTF-8")@ResponseBodypublic ResponseData updateUser(HttpServletRequest request,User user){ResponseData responseData=new ResponseData();try {userService.updateUser(user);responseData.setStatus(0);responseData.setMsg("修改成功");}catch(Exception e){responseData.setStatus(1);responseData.setMsg("修改失败");}return  responseData;}/*** 获取菜单* @param request* @param id* @return*/@RequiresPermissions(value={"user:getNode"})@RequestMapping(value="getRole/{id}", method = RequestMethod.GET, produces = "application/json;charset=UTF-8")@ResponseBodypublic ResponseData getRole(HttpServletRequest request,@PathVariable("id") String id){ResponseData responseData=new ResponseData();try {List<Menu> menu = userService.getRole(id);responseData.setStatus(0);responseData.setData(menu);responseData.setMsg("获取成功");}catch(Exception e){responseData.setStatus(1);responseData.setMsg("获取失败");}return  responseData;}/*** 插入菜单* @param request* @param id* @param urls* @return*/@RequiresPermissions(value={"user:addNode"})@RequestMapping(value="insertNode", method = RequestMethod.POST, produces = "application/json;charset=UTF-8")@ResponseBodypublic ResponseData insertNode(HttpServletRequest request,String id,String urls){ResponseData responseData=new ResponseData();try {userService.saveNode(id,urls);responseData.setStatus(0);responseData.setMsg("添加成功");}catch(Exception e){responseData.setStatus(1);responseData.setMsg("添加失败");}return  responseData;}@RequestMapping(value="list", method = RequestMethod.GET, produces = "application/json;charset=UTF-8")@ResponseBodypublic ResponseData list(HttpServletRequest request){ResponseData responseData=new ResponseData();try {List<String> list = new ArrayList<>();list.add("123");list.add("456");list.add("789");//responseData = userService.login(user);responseData.setStatus(0);responseData.setMsg("获取数据成功");responseData.setData(list);}catch(Exception e){responseData.setStatus(1);responseData.setMsg("获取数据失败");}return  responseData;}
}
package com.waysoft.modules.business.integrate.role.controller;import java.util.List;import javax.servlet.http.HttpServletRequest;import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;import com.waysoft.common.ResponseData;
import com.waysoft.global.model.Menu;
import com.waysoft.global.model.Role;
import com.waysoft.modules.business.integrate.role.service.RoleService;@Controller
@RequestMapping("/role")
public class RoleController {@Autowiredprivate RoleService roleService;/*** 添加角色* @param request* @param role* @return*/@RequiresPermissions("role:add")@RequestMapping(value="insertRole", method = RequestMethod.POST, produces = "application/json;charset=UTF-8")@ResponseBodypublic ResponseData insertRole(HttpServletRequest request,Role role){ResponseData responseData=new ResponseData();try {roleService.insertRole(role);responseData.setStatus(0);responseData.setMsg("添加成功");}catch(Exception e){responseData.setStatus(1);responseData.setMsg("添加失败");}return  responseData;}/*** 回显角色* @param request* @param id* @return*/@RequiresPermissions("role:get")@RequestMapping(value="getRole/{id}", method = RequestMethod.GET, produces = "application/json;charset=UTF-8")@ResponseBodypublic ResponseData getRole(HttpServletRequest request,@PathVariable("id") String id){ResponseData responseData=new ResponseData();try {Role role = roleService.getRole(id);responseData.setStatus(0);responseData.setData(role);responseData.setMsg("获取成功");}catch(Exception e){responseData.setStatus(1);responseData.setMsg("获取失败");}return  responseData;}/*** 修改角色* @param request* @param role* @return*/@RequiresPermissions("role:update")@RequestMapping(value="updateRole", method = RequestMethod.POST, produces = "application/json;charset=UTF-8")@ResponseBodypublic ResponseData updateRole(HttpServletRequest request,Role role){ResponseData responseData=new ResponseData();try {roleService.updateRole(role);responseData.setStatus(0);responseData.setMsg("修改成功");}catch(Exception e){responseData.setStatus(1);responseData.setMsg("修改失败");}return  responseData;}/*** 获取菜单* @param request* @param id* @return*/@RequiresPermissions("role:getNode")@RequestMapping(value="getMenu/{id}", method = RequestMethod.GET, produces = "application/json;charset=UTF-8")@ResponseBodypublic ResponseData getMenu(HttpServletRequest request,@PathVariable("id") String id){ResponseData responseData=new ResponseData();try {List<Menu> menu = roleService.getMenu(id);responseData.setStatus(0);responseData.setData(menu);responseData.setMsg("获取成功");}catch(Exception e){responseData.setStatus(1);responseData.setMsg("获取失败");}return  responseData;}/*** 插入菜单* @param request* @param id* @param urls* @return*/@RequiresPermissions("role:addNode")@RequestMapping(value="insertNode", method = RequestMethod.POST, produces = "application/json;charset=UTF-8")@ResponseBodypublic ResponseData insertNode(HttpServletRequest request,String id,String urls){ResponseData responseData=new ResponseData();try {roleService.saveNode(id,urls);responseData.setStatus(0);responseData.setMsg("添加成功");}catch(Exception e){responseData.setStatus(1);responseData.setMsg("添加失败");}return  responseData;}
}

方法上我基本上都加入了权限验证   @RequiresPermissions("role:add")

由于我都是从数据库中读取的,所以我需要重写AuthorizingRealm

package com.waysoft.common.shiro;import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;import com.waysoft.global.model.User;
import com.waysoft.modules.business.integrate.role.dao.RoleDao;
import com.waysoft.modules.business.integrate.user.service.UserService;public class UserRealm extends AuthorizingRealm {@Autowiredprivate UserService userService;@Autowiredprivate RoleDao roleDao;/*** 授权验证*/@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg0) {System.out.println("=============");Subject subject = SecurityUtils.getSubject();Session session = subject.getSession();User user = (User)session.getAttribute("user");String[] ids = userService.getRoleIdByUserId(user.getId()+"");SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();if(ids.length > 0){List<String> asList = Arrays.asList(ids);info.addRoles(asList);for(String id : asList){String permsName = roleDao.getPermsByid(id);String perms [] = permsName.split(",");for(String prem :perms){info.addStringPermission(prem);}}return info;}return null; }/*** 登录验证*/@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {// 账户名String username = (String) authenticationToken.getPrincipal();User user = userService.findUser(username);if(user != null){return new SimpleAuthenticationInfo(username,user.getPassword(),null,getName());}else{return null;}}}

网上有很多种方法可以插入权限信息,但我用都不好使。比如:info.addStringPermissions(permissions);,没成功过,也在这卡了半天。最后我是使用addStringPermission实现的,原本我还有以为这样循环会覆盖原来的值,经测试,并没有。

之后就是重写PermissionsAuthorizationFilter

这个真是太坑了。差点被他搞死,看下源码

画红框的就是坑,它所验证的是一个,或者全部符合,是全等关系,而不是包含关系。

我要重写成包含关系

有一个符合就通过。

自定义ShiroFilterFactoryBean

package com.waysoft.common.shiro;import java.text.MessageFormat;
import java.util.HashMap;
import java.util.List;
import java.util.Map;import org.apache.shiro.config.Ini;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.util.CollectionUtils;
import org.apache.shiro.web.filter.mgt.DefaultFilterChainManager;
import org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver;
import org.apache.shiro.web.servlet.AbstractShiroFilter;
import org.springframework.beans.factory.annotation.Autowired;import com.waysoft.modules.business.integrate.role.dao.RoleDao;public class MyShiroFilterFactoryBean extends ShiroFilterFactoryBean {private static final String roles = "authc,perms[{0}]";// perms@Autowiredprivate RoleDao roleDao;@Overridepublic void setFilterChainDefinitions(String definitions) {//System.out.println("权限认证");Ini ini = new Ini();ini.load(definitions);Ini.Section section = ini.getSection("urls");if (CollectionUtils.isEmpty(section)) {section = ini.getSection("");}Map<String,String> data = new HashMap<String,String>();// 从数据读取出数据List<Map<String,String>> menuRole = roleDao.getPerms_();for(Map<String,String> map : menuRole){if(data.containsKey(map.get("url"))){String str = data.get(map.get("url"))+","+map.get("perms_");data.put(map.get("url"), str);}else{data.put(map.get("url"), map.get("perms_"));}}for(String url : data.keySet()){String str = MessageFormat.format(roles,data.get(url));System.out.println(url+"="+str);section.put(url, str);}section.put("/**", "authc");super.setFilterChainDefinitionMap(section);}public void update(){synchronized (this) {try {AbstractShiroFilter shiroFilter = (AbstractShiroFilter)this.getObject();PathMatchingFilterChainResolver resolver = (PathMatchingFilterChainResolver)shiroFilter.getFilterChainResolver();DefaultFilterChainManager manager = (DefaultFilterChainManager)resolver.getFilterChainManager();manager.getFilterChains().clear();this.getFilterChainDefinitionMap().clear();Map<String, String> chains = this.getFilterChainDefinitionMap();Map<String,String> data = new HashMap<String,String>();// 从数据读取出数据List<Map<String,String>> menuRole = roleDao.getPerms_();for(Map<String,String> map : menuRole){if(data.containsKey(map.get("url"))){String str = data.get(map.get("url"))+","+map.get("perms_");data.put(map.get("url"), str);}else{data.put(map.get("url"), map.get("perms_"));}}for(String url : data.keySet()){String str = MessageFormat.format(roles,data.get(url));chains.put(url, str);}chains.put("/**", "authc");if (!(CollectionUtils.isEmpty(chains))) {for (Map.Entry entry : chains.entrySet()) {String url = (String) entry.getKey();String chainDefinition = (String) entry.getValue();manager.createChain(url, chainDefinition);}}} catch (Exception e) {e.printStackTrace();}}}public static void main(String[] args) {System.out.println(MessageFormat.format(roles,2));}
}

还有就是要在xml中加入如下内容,否则注解不起作用

<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/><bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"depends-on="lifecycleBeanPostProcessor"><property name="proxyTargetClass" value="true" /></bean>    <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor"><property name="securityManager" ref="securityManager"/></bean>

资料下载地址:https://download.csdn.net/download/xcc_2269861428/11348378

springmvc整个shiro实现Perms的权限认证(细粒度)(三)相关推荐

  1. springboot整合shiro + jwt + redis实现权限认证(上手即用)

    目录 前言 项目结构 依赖导入 建数据库表 建表语句 使用插件生成增删改查 添加MyRealm 添加ShiroConfig 添加JwtFilter JWT相关得类 JwtToken JwtAudien ...

  2. jwt无状态权限认证(pings-shiro-jwt)

    单用户并发访问的问题 当用户AccessToken失效,用户使用该失效的AccessToken同时发起多个请求,会产生多AccessToken和RefreshToken认证失败问题: 多AccessT ...

  3. shiro框架多realm登录认证配置

    我们做shiro框架经常会遇到这种情况,用户数量很多,又不在同一个表里,比如管理员一个表,用户一个表,商家一个表.这时我们就需要用到多realm来配置让他们用不同得realm来进行登录 首先来说思路, ...

  4. SpringBoot学习:整合shiro(身份认证和权限认证),使用EhCache缓存

    一.在pom中引入依赖jar包 1 <properties> 2 <shiro.version>1.3.2</shiro.version> 3 </prope ...

  5. 学习Spring Boot:(十三)配置 Shiro 权限认证

    经过前面学习 Apache Shiro ,现在结合 Spring Boot 使用在项目里,进行相关配置. 正文 添加依赖 在 pom.xml 文件中添加 shiro-spring 的依赖: <d ...

  6. springMVC整合shiro权限框架示例与实践

    2019独角兽企业重金招聘Python工程师标准>>> 为什么写这篇文章 看过那么多框架.教程,大部分shiro的文章或教程是我见过思路最糟糕的.作者完不清楚想要表达什么起到什么作用 ...

  7. SpringMvc 集成 shiro 实现权限角色管理-maven

    2019独角兽企业重金招聘Python工程师标准>>> SpringMvc 集成 shiro 实现权限角色管理 1.项目清单展示 2.项目源码解析  1)spring-context ...

  8. 详解比springSecurity和shiro更简单优雅的轻量级Sa-Token框架,比如登录认证,权限认证,单点登录,OAuth2.0,分布式Session会话,微服务网关鉴权

    文章目录 1. 技术选型 2. Sa-Token概述 2.1 简单介绍 2.2 登录认证 2.3 权限认证 3. 功能一览 4. Sa-Token使用 4.1 引入Sa-Token依赖 4.2 Sa- ...

  9. Shiro中进行角色与权限认证流程

    场景 使用Shiro的JdbcRealm实现查询数据库进行身份认证: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/9010599 ...

最新文章

  1. 关于java环境配置问题
  2. 【目标检测】RCNN算法详解
  3. 360加固分析(二)
  4. 【LINUX】Oracle数据库 linux磁盘头数据损坏修复
  5. DotText源码阅读(7) --Pingback/TrackBack
  6. 使用PowerMock模拟构造函数
  7. html悬浮窗口退出,网页中可关闭的漂浮窗口实现
  8. 【技术】一份完全解读:是什么使神经网络变成图神经网络?
  9. 使用Spark Shell开发运行Spark程序
  10. revit建筑样板_Revit怎么玩转预制管道?这技能可有点高级了啊
  11. RTT设置删除空闲钩子函数想到函数指针和回调函数
  12. Gym101237C The Palindrome Extraction Manacher、SAM、倍增
  13. java web 开发环境布置学习笔记1
  14. 怎么卸载Office2007兼容包?
  15. typedef用法,函数指针
  16. 大学计算机实践基础教程,大学计算机基础实践教程(微课版)
  17. 笔记1——海康威视摄像头关闭声音
  18. 【Office使用技巧】word内公式相关快捷键
  19. 【整理】GOS附件的上传与下载
  20. 基于 Flutter 视频客户端 Vistor【已开源】

热门文章

  1. Windows下文本生成图像AI画图尝鲜体验
  2. golang中io/ioutil.readdir和path/filepath.walk遍历获取目录下文件性能比较
  3. 软件的接口设计图_App软件开发的完整在线流程(一看就懂)
  4. RUI topic 3
  5. Java中抽象类 abstract和interface的区别
  6. SharePoint 2013 实现多级审批工作流
  7. 九、Callable接口的使用
  8. Slackware穿墙术(转)
  9. 琢金广告浅谈企业进行网站优化的方法
  10. SAS学习笔记44 宏函数