springmvc整个shiro实现Perms的权限认证(细粒度)(三)
前言:上一篇文章讲述了如何使用角色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的权限认证(细粒度)(三)相关推荐
- springboot整合shiro + jwt + redis实现权限认证(上手即用)
目录 前言 项目结构 依赖导入 建数据库表 建表语句 使用插件生成增删改查 添加MyRealm 添加ShiroConfig 添加JwtFilter JWT相关得类 JwtToken JwtAudien ...
- jwt无状态权限认证(pings-shiro-jwt)
单用户并发访问的问题 当用户AccessToken失效,用户使用该失效的AccessToken同时发起多个请求,会产生多AccessToken和RefreshToken认证失败问题: 多AccessT ...
- shiro框架多realm登录认证配置
我们做shiro框架经常会遇到这种情况,用户数量很多,又不在同一个表里,比如管理员一个表,用户一个表,商家一个表.这时我们就需要用到多realm来配置让他们用不同得realm来进行登录 首先来说思路, ...
- SpringBoot学习:整合shiro(身份认证和权限认证),使用EhCache缓存
一.在pom中引入依赖jar包 1 <properties> 2 <shiro.version>1.3.2</shiro.version> 3 </prope ...
- 学习Spring Boot:(十三)配置 Shiro 权限认证
经过前面学习 Apache Shiro ,现在结合 Spring Boot 使用在项目里,进行相关配置. 正文 添加依赖 在 pom.xml 文件中添加 shiro-spring 的依赖: <d ...
- springMVC整合shiro权限框架示例与实践
2019独角兽企业重金招聘Python工程师标准>>> 为什么写这篇文章 看过那么多框架.教程,大部分shiro的文章或教程是我见过思路最糟糕的.作者完不清楚想要表达什么起到什么作用 ...
- SpringMvc 集成 shiro 实现权限角色管理-maven
2019独角兽企业重金招聘Python工程师标准>>> SpringMvc 集成 shiro 实现权限角色管理 1.项目清单展示 2.项目源码解析 1)spring-context ...
- 详解比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- ...
- Shiro中进行角色与权限认证流程
场景 使用Shiro的JdbcRealm实现查询数据库进行身份认证: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/9010599 ...
最新文章
- 关于java环境配置问题
- 【目标检测】RCNN算法详解
- 360加固分析(二)
- 【LINUX】Oracle数据库 linux磁盘头数据损坏修复
- DotText源码阅读(7) --Pingback/TrackBack
- 使用PowerMock模拟构造函数
- html悬浮窗口退出,网页中可关闭的漂浮窗口实现
- 【技术】一份完全解读:是什么使神经网络变成图神经网络?
- 使用Spark Shell开发运行Spark程序
- revit建筑样板_Revit怎么玩转预制管道?这技能可有点高级了啊
- RTT设置删除空闲钩子函数想到函数指针和回调函数
- Gym101237C The Palindrome Extraction Manacher、SAM、倍增
- java web 开发环境布置学习笔记1
- 怎么卸载Office2007兼容包?
- typedef用法,函数指针
- 大学计算机实践基础教程,大学计算机基础实践教程(微课版)
- 笔记1——海康威视摄像头关闭声音
- 【Office使用技巧】word内公式相关快捷键
- 【整理】GOS附件的上传与下载
- 基于 Flutter 视频客户端 Vistor【已开源】