SpringBoot + Redis + Shiro 实现权限管理
文章主要是针对shiro进行权限配置,只针对角色进行了权限过滤。
GitHub:https://github.com/stevencxb/blog
数据库脚本
-- ---------------------------- -- Table structure for sys_menu -- ---------------------------- DROP TABLE IF EXISTS `sys_menu`; CREATE TABLE `sys_menu` (`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',`pid` bigint(20) NULL DEFAULT 0 COMMENT '父id',`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '名称',`type` int(11) NULL DEFAULT NULL COMMENT '类型(1:模块;2:菜单)',`url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '路径',`sort` int(11) NULL DEFAULT NULL COMMENT '排序',PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 20 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '系统菜单' ROW_FORMAT = Dynamic;-- ---------------------------- -- Table structure for sys_role -- ---------------------------- DROP TABLE IF EXISTS `sys_role`; CREATE TABLE `sys_role` (`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '角色id',`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '名称',`remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '描述',PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '角色' ROW_FORMAT = Dynamic;-- ---------------------------- -- Table structure for sys_role_menu -- ---------------------------- DROP TABLE IF EXISTS `sys_role_menu`; CREATE TABLE `sys_role_menu` (`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',`role_id` bigint(20) NOT NULL,`menu_id` bigint(20) NOT NULL,PRIMARY KEY (`id`) USING BTREE,UNIQUE INDEX `role_id`(`role_id`, `menu_id`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 171 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '角色-菜单' ROW_FORMAT = Dynamic;-- ---------------------------- -- Table structure for sys_user -- ---------------------------- DROP TABLE IF EXISTS `sys_user`; CREATE TABLE `sys_user` (`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '用户id',`name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '姓名',`user_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '用户名',`nick_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '昵称',`birthday` date NULL DEFAULT NULL COMMENT '出生日期',`phone` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '手机号',`email` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '邮箱',`pwd` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '密码',`sex` tinyint(2) NULL DEFAULT NULL COMMENT '性别(1:男;2:女)',`intro` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '个人简介',`head_img` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '头像地址',`status` tinyint(2) NOT NULL DEFAULT 1 COMMENT '状态(1:正常:2:冻结)',`last_login_time` datetime(0) NULL DEFAULT NULL COMMENT '最后登录时间',`create_time` datetime(0) NOT NULL COMMENT '创建时间',PRIMARY KEY (`id`) USING BTREE,UNIQUE INDEX `username`(`user_name`) USING BTREE,UNIQUE INDEX `phone`(`phone`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 5 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '用户表' ROW_FORMAT = Dynamic;-- ---------------------------- -- Table structure for sys_user_role -- ---------------------------- DROP TABLE IF EXISTS `sys_user_role`; CREATE TABLE `sys_user_role` (`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',`user_id` bigint(20) NOT NULL COMMENT '用户id',`role_id` bigint(20) NULL DEFAULT NULL COMMENT '角色id',PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 12 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '用户-角色' ROW_FORMAT = Dynamic;
maven配置
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency>
<dependency><groupId>org.crazycake</groupId><artifactId>shiro-redis</artifactId><version>2.4.2.1-RELEASE</version></dependency><dependency><groupId>com.github.theborakompanioni</groupId><artifactId>thymeleaf-extras-shiro</artifactId><version>2.0.0</version></dependency>
ShiroConfig
package com.cxb.blog.config;import at.pollux.thymeleaf.shiro.dialect.ShiroDialect; import com.cxb.blog.service.ISysMenuService; import com.cxb.blog.utils.ShiroUtil; import lombok.extern.slf4j.Slf4j; import org.apache.shiro.mgt.SecurityManager; import org.apache.shiro.spring.LifecycleBeanPostProcessor; import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor; import org.apache.shiro.spring.web.ShiroFilterFactoryBean; import org.apache.shiro.web.mgt.DefaultWebSecurityManager; import org.apache.shiro.web.session.mgt.DefaultWebSessionManager; import org.crazycake.shiro.RedisCacheManager; import org.crazycake.shiro.RedisManager; import org.crazycake.shiro.RedisSessionDAO; import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration;import javax.servlet.Filter; import java.util.LinkedHashMap; import java.util.Map;/*** @Title: ShiroConfig* @Description: ShiroConfig* @Author <a href="mailto:chenxb1993@126.com">陈晓博</a>* @Date 2019-05-14 14:01* @Version V1.0*/ @Slf4j @Configuration public class ShiroConfig {@Value("${spring.redis.host}")private String host;@Value("${spring.redis.password}")private String password;@Value("${spring.redis.port}")private String port;@Value("${spring.redis.timeout}")private String timeout;@Value("${spring.redis.database}")private String database;@Autowiredprivate ISysMenuService sysMenuService;@Beanpublic ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();// 必须设置 SecurityManager shiroFilterFactoryBean.setSecurityManager(securityManager);// setLoginUrl 如果不设置值,默认会自动寻找Web工程根目录下的"/login.jsp"页面 或 "/login" 映射shiroFilterFactoryBean.setLoginUrl("/login");// 设置无权限时跳转的 url;shiroFilterFactoryBean.setUnauthorizedUrl("/403");Map<String, Filter> filtersMap = new LinkedHashMap<>();filtersMap.put("roleOrFilter",new RolesOrFilterAuthorizationFilter());//可以配置RoleOrFilter的Bean filtersMap.put("kickout",kickoutSessionControlFilter());shiroFilterFactoryBean.setFilters(filtersMap);// 设置拦截器Map<String, String> filterChainDefinitionMap = ShiroUtil.getFilterChainDefinitionMap(sysMenuService);shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);log.info("Shiro拦截器工厂类注入成功");return shiroFilterFactoryBean;}@Beanpublic SecurityManager securityManager() {DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();// 设置realm. securityManager.setRealm(shiroRealm());// 自定义缓存实现 使用redis securityManager.setCacheManager(cacheManager());// 自定义session管理 使用redis securityManager.setSessionManager(sessionManager());return securityManager;}/*** 身份认证realm; (这个需要自己写,账号密码校验;权限等)** @return*/@Beanpublic RealmConfig shiroRealm() {RealmConfig realmConfig = new RealmConfig();return realmConfig;}/*** cacheManager 缓存 redis实现* 使用的是shiro-redis开源插件** @return*/public RedisCacheManager cacheManager() {RedisCacheManager redisCacheManager = new RedisCacheManager();redisCacheManager.setRedisManager(redisManager());return redisCacheManager;}/*** 配置shiro redisManager* 使用的是shiro-redis开源插件** @return*/public RedisManager redisManager() {RedisManager redisManager = new RedisManager();redisManager.setHost(host);redisManager.setPort(Integer.parseInt(port));redisManager.setExpire(1800);// 配置缓存过期时间 redisManager.setTimeout(Integer.parseInt(timeout));redisManager.setPassword(password);return redisManager;}/*** Session Manager* 使用的是shiro-redis开源插件*/@Beanpublic DefaultWebSessionManager sessionManager() {DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();sessionManager.setSessionDAO(redisSessionDAO());return sessionManager;}/*** RedisSessionDAO shiro sessionDao层的实现 通过redis* 使用的是shiro-redis开源插件*/@Beanpublic RedisSessionDAO redisSessionDAO() {RedisSessionDAO redisSessionDAO = new RedisSessionDAO();redisSessionDAO.setRedisManager(redisManager());return redisSessionDAO;}/*** 限制同一账号登录同时登录人数控制** @return*/@Beanpublic KickoutSessionControlFilter kickoutSessionControlFilter() {KickoutSessionControlFilter kickoutSessionControlFilter = new KickoutSessionControlFilter();kickoutSessionControlFilter.setCacheManager(cacheManager());kickoutSessionControlFilter.setSessionManager(sessionManager());kickoutSessionControlFilter.setKickoutAfter(false);kickoutSessionControlFilter.setMaxSession(1);kickoutSessionControlFilter.setKickoutUrl("/kickout");return kickoutSessionControlFilter;}/**** 授权所用配置** @return*/@Beanpublic DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator() {DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);return defaultAdvisorAutoProxyCreator;}/**** 使授权注解起作用不如不想配置可以在pom文件中加入* <dependency>*<groupId>org.springframework.boot</groupId>*<artifactId>spring-boot-starter-aop</artifactId>*</dependency>* @param securityManager* @return*/@Beanpublic AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager){AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);return authorizationAttributeSourceAdvisor;}/*** Shiro生命周期处理器**/@Beanpublic static LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {return new LifecycleBeanPostProcessor();}/*** ShiroDialect,为了在thymeleaf里使用shiro的标签的bean** @return*/@Beanpublic ShiroDialect shiroDialect() {return new ShiroDialect();} }
RealmConfig
package com.cxb.blog.config;import com.cxb.blog.dao.SysMenuDao; import com.cxb.blog.domain.DO.SysMenuDO; import com.cxb.blog.domain.DO.SysUserDO; import com.cxb.blog.enums.SysUserStatus; import com.cxb.blog.exception.SysUserStatusException; import com.cxb.blog.service.ISysUserRoleService; import com.cxb.blog.service.ISysUserService; import com.cxb.blog.utils.RegexUtil; import lombok.extern.slf4j.Slf4j; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.*; import org.apache.shiro.authz.AuthorizationInfo; import org.apache.shiro.authz.SimpleAuthorizationInfo; import org.apache.shiro.realm.AuthorizingRealm; import org.apache.shiro.subject.PrincipalCollection; import org.apache.shiro.subject.Subject; import org.springframework.beans.factory.annotation.Autowired;import java.util.HashSet; import java.util.List; import java.util.Set;/*** @Title: RealmConfig* @Description: shiro realm* @Author <a href="mailto:chenxb1993@126.com">陈晓博</a>* @Date 2019-05-14 14:01* @Version V1.0*/ @Slf4j public class RealmConfig extends AuthorizingRealm {//如果项目中用到了事物,@Autowired注解会使事物失效,可以自己用get方法获取值 @Autowiredprivate ISysUserService sysUserService;@Autowiredprivate ISysUserRoleService sysUserRoleService;@Autowiredprivate SysMenuDao sysMenuDao;/*** 认证信息.(身份验证) : Authentication 是用来验证用户身份**/@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authctoken) throws AuthenticationException {log.info("---------------- 执行 Shiro 凭证认证 ----------------------");UsernamePasswordToken token = (UsernamePasswordToken) authctoken;String name = token.getUsername();String password = String.valueOf(token.getPassword());// 从数据库获取对应用户名密码的用户 SysUserDO userDO;if (RegexUtil.checkMobile(name)) {userDO = sysUserService.getByPhone(name);}else {userDO = sysUserService.getByUserName(name);}if (userDO == null) {throw new UnknownAccountException("账号或密码不正确");}// 密码错误if (!password.equals(userDO.getPwd())) {throw new IncorrectCredentialsException("账号或密码不正确");}if (userDO.getStatus() != SysUserStatus.NORMAL.getStatus()){throw new SysUserStatusException("用户状态异常");}Subject subject = SecurityUtils.getSubject();subject.getSession().setAttribute("userName", name);subject.getSession().setAttribute("id", userDO.getId());log.info("---------------- Shiro 凭证认证成功 ----------------------");SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(name, //用户password, //密码getName() //realm name );return authenticationInfo;}/*** 授权*/@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {log.info("---------------- 执行 Shiro 权限获取 ---------------------");String principal = (String)principals.getPrimaryPrincipal();SysUserDO sysUserDO = sysUserService.getByUserName(principal);SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();Set<String> roles = sysUserRoleService.getRoleIdByUserId(sysUserDO.getId());authorizationInfo.addRoles(roles); // // List<SysMenuDO> list = sysMenuDao.getSysMenuByUserId(sysUserDO.getId()); // Set<String> set=new HashSet<>(); // for (SysMenuDO sysMenuDO : list){ // set.add(sysMenuDO.getUrl()+"/**"); // } // authorizationInfo.addStringPermissions(set);log.info("---------------- Shiro 权限获取成功 ----------------------");return authorizationInfo;} }
RolesOrFilterAuthorizationFilter
package com.cxb.blog.config;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;/*** @Title: RolesOrFilterAuthorizationFilter* @Description: 角色过滤* @Author <a href="mailto:chenxb1993@126.com">陈晓博</a>* @Date 2019-05-23 15:01* @Version V1.0*/ public class RolesOrFilterAuthorizationFilter extends RolesAuthorizationFilter{public boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws IOException {Subject subject = this.getSubject(request, response);String[] rolesArray = (String[])((String[])mappedValue);if (rolesArray != null && rolesArray.length != 0) {Set<String> roles = CollectionUtils.asSet(rolesArray);for (String role : roles){if (subject.hasRole(role)){return true;}}return false;} else {return true;}} }
5.KickoutSessionControlFilter
package com.cxb.blog.config;import com.alibaba.fastjson.JSON; import org.apache.shiro.cache.Cache; import org.apache.shiro.cache.CacheManager; import org.apache.shiro.session.Session; import org.apache.shiro.session.mgt.DefaultSessionKey; import org.apache.shiro.session.mgt.SessionManager; import org.apache.shiro.subject.Subject; import org.apache.shiro.web.filter.AccessControlFilter; import org.apache.shiro.web.util.WebUtils;import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import java.io.IOException; import java.io.PrintWriter; import java.io.Serializable; import java.util.Deque; import java.util.HashMap; import java.util.LinkedList; import java.util.Map;/*** @Title: KickoutSessionControlFilter* @Description: 被踢出控制* @Author <a href="mailto:chenxb1993@126.com">陈晓博</a>* @Date 2019-05-14 14:03* @Version V1.0*/ public class KickoutSessionControlFilter extends AccessControlFilter {private String kickoutUrl; //踢出后到的地址private boolean kickoutAfter = false; //踢出之前登录的/之后登录的用户 默认踢出之前登录的用户private int maxSession = 1; //同一个帐号最大会话数 默认1private SessionManager sessionManager;private Cache<String, Deque<Serializable>> cache;public void setKickoutUrl(String kickoutUrl) {this.kickoutUrl = kickoutUrl;}public void setKickoutAfter(boolean kickoutAfter) {this.kickoutAfter = kickoutAfter;}public void setMaxSession(int maxSession) {this.maxSession = maxSession;}public void setSessionManager(SessionManager sessionManager) {this.sessionManager = sessionManager;}//设置Cache的key的前缀public void setCacheManager(CacheManager cacheManager) {this.cache = cacheManager.getCache("shiro_redis_cache");}@Overrideprotected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {return false;}@Overrideprotected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {Subject subject = getSubject(request, response);if(!subject.isAuthenticated() && !subject.isRemembered()) {//如果没有登录,直接进行之后的流程return true;}Session session = subject.getSession();String userName = (String) subject.getPrincipal();Serializable sessionId = session.getId();//读取缓存 没有就存入Deque<Serializable> deque = cache.get(userName);//如果此用户没有session队列,也就是还没有登录过,缓存中没有//就new一个空队列,不然deque对象为空,会报空指针if(deque==null){deque = new LinkedList<Serializable>();}//如果队列里没有此sessionId,且用户没有被踢出;放入队列if(!deque.contains(sessionId) && session.getAttribute("kickout") == null) {//将sessionId存入队列 deque.push(sessionId);//将用户的sessionId队列缓存 cache.put(userName, deque);}//如果队列里的sessionId数超出最大会话数,开始踢人while(deque.size() > maxSession) {Serializable kickoutSessionId = null;if(kickoutAfter) { //如果踢出后者kickoutSessionId = deque.removeFirst();//踢出后再更新下缓存队列 cache.put(userName, deque);} else { //否则踢出前者kickoutSessionId = deque.removeLast();//踢出后再更新下缓存队列 cache.put(userName, deque);}try {//获取被踢出的sessionId的session对象Session kickoutSession = sessionManager.getSession(new DefaultSessionKey(kickoutSessionId));if(kickoutSession != null) {//设置会话的kickout属性表示踢出了kickoutSession.setAttribute("kickout", true);}} catch (Exception e) {//ignore exception }}//如果被踢出了,直接退出,重定向到踢出后的地址if (session.getAttribute("kickout") != null) {//会话被踢出了try {//退出登录 subject.logout();} catch (Exception e) { //ignore }saveRequest(request);Map<String, String> resultMap = new HashMap<String, String>();//判断是不是Ajax请求if ("XMLHttpRequest".equalsIgnoreCase(((HttpServletRequest) request).getHeader("X-Requested-With"))) {resultMap.put("user_status", "300");resultMap.put("message", "您已经在其他地方登录,请重新登录!");//输出json串 out(response, resultMap);}else{//重定向 WebUtils.issueRedirect(request, response, kickoutUrl);}return false;}return true;}private void out(ServletResponse hresponse, Map<String, String> resultMap)throws IOException {try {hresponse.setCharacterEncoding("UTF-8");PrintWriter out = hresponse.getWriter();out.println(JSON.toJSONString(resultMap));out.flush();out.close();} catch (Exception e) {System.err.println("KickoutSessionFilter.class 输出JSON异常,可以忽略。");}}}
ShiroFilerChainManager
package com.cxb.blog.config;import com.cxb.blog.service.ISysMenuService; import com.cxb.blog.utils.ShiroUtil; import lombok.extern.slf4j.Slf4j; import org.apache.shiro.spring.web.ShiroFilterFactoryBean; 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 org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional;/*** @Title: ShiroFilerChainManager* @Description: ShiroFilerChainManager* @Author <a href="mailto:chenxb1993@126.com">陈晓博</a>* @Date 2019-05-23 15:30* @Version V1.0*/ @Slf4j @Component("shiroFilerChainManager") @Transactional(readOnly=true) public class ShiroFilerChainManager {@Autowiredprivate ShiroFilterFactoryBean shiroFilterFactoryBean;@Autowiredprivate ISysMenuService sysMenuService;/*** 重载过滤链*/public void reloadFilterChains() {AbstractShiroFilter shiroFilter = null;try {shiroFilter = (AbstractShiroFilter) shiroFilterFactoryBean.getObject();} catch (Exception e) {log.error("getShiroFilter from shiroFilterFactoryBean error!", e);throw new RuntimeException("get ShiroFilter from shiroFilterFactoryBean error!");}PathMatchingFilterChainResolver filterChainResolver = (PathMatchingFilterChainResolver) shiroFilter.getFilterChainResolver();DefaultFilterChainManager manager = (DefaultFilterChainManager) filterChainResolver.getFilterChainManager();// 清空老的权限控制 manager.getFilterChains().clear();shiroFilterFactoryBean.getFilterChainDefinitionMap().clear();shiroFilterFactoryBean.setFilterChainDefinitionMap(ShiroUtil.getFilterChainDefinitionMap(sysMenuService));System.out.println("Shiro拦截器工厂类注入成功");}}
ShiroUtil
package com.cxb.blog.utils;import com.cxb.blog.domain.VO.SysMenuFilterVO; import com.cxb.blog.service.ISysMenuService;import java.util.LinkedHashMap; import java.util.List; import java.util.Map;/*** @Title: ShiroUtil* @Description: shiro工具类* @Author <a href="mailto:chenxb1993@126.com">陈晓博</a>* @Date 2019-05-23 15:37* @Version V1.0*/ public class ShiroUtil {public static Map<String, String> getFilterChainDefinitionMap(ISysMenuService sysMenuService){Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();List<SysMenuFilterVO> list = sysMenuService.selectAll(); // //游客,开发权限 // filterChainDefinitionMap.put("/guest/**", "anon"); // //用户,需要角色权限 “user” // filterChainDefinitionMap.put("/user/**", "roles[user]"); // //管理员,需要角色权限 “admin” // filterChainDefinitionMap.put("/admin/**", "roles[admin]"); // //开放登陆接口 // filterChainDefinitionMap.put("/login", "anon"); // //其余接口一律拦截//主要这行代码必须放在所有权限设置的最后,不然会导致所有 url 都被拦截for(SysMenuFilterVO filter : list){filterChainDefinitionMap.put(filter.getUrl()+"/**","roleOrFilter["+(filter.getRoles()==null?"":filter.getRoles())+"]");}filterChainDefinitionMap.put("/**", "kickout,anon");return filterChainDefinitionMap;}}
转载于:https://www.cnblogs.com/chenxbo/p/11002392.html
SpringBoot + Redis + Shiro 实现权限管理相关推荐
- 《SpringBoot与Shiro整合-权限管理实战---从构建到模拟数据库登入》
<SpringBoot与Shiro整合-权限管理实战> ---- 从构建到模拟数据库登入 ---- 点击下载源码 ---- 或者查看? 文章目录 <SpringBoot与Shiro整 ...
- SpringBoot整合Shiro实现权限管理与登陆注册
前言 Shiro解决了什么问题? 互联网无非就是一些用户C想要使用一些服务S的资源去完成某件事,S的资源不能说给谁用就给谁用,因此产生了权限的概念,即C必须有权限才能操作S的资源.S如何确定C就是C呢 ...
- SpringBoot整合Shiro实现权限管理,经典实战教程
String username = authenticationToken.getPrincipal().toString(); if(!username.equals("zhang&quo ...
- SpringBoot整合Shiro实现权限管理
超详细的Java知识点路线图 目录 概述 RBAC权限管理 Shiro介绍 Shiro入门 自定义Realm 密码加密加盐 SpringBoot+MyBatis+Shiro整合 RememberMe ...
- 个人笔记 springboot整合shiro实现权限管理,前端使用vue 10155
转载自github,地址https://github.com/Heeexy/SpringBoot-Shiro-Vue 目录结构: application.yml spring:datasource:u ...
- 【超详细】SpringBoot与Shiro整合-权限管理实战实操(附源码地址)
一.搭建SpringBoot开发环境 1. 安装好开发软件和Maven等 开发工具:Spring Tool Suite(TST) Maven :3.3.9 jdk:1.8 2. 创建springboo ...
- SpringBoot 基于Shiro + Jwt + Redis的用户权限管理 (三) 鉴权
项目Github地址: https://github.com/baiye21/ShiroDemo SpringBoot 基于Shiro + Jwt + Redis的用户权限管理 (一) 简介与配置 S ...
- spring boot整合shiro继承redis_spring-boot-plus集成Shiro+JWT权限管理
SpringBoot+Shiro+JWT权限管理 Shiro Apache Shiro是一个强大且易用的Java安全框架,执行身份验证.授权.密码和会话管理. 使用Shiro的易于理解的API,您可以 ...
- 如何在 Spring Boot 中用 Shiro 实现权限管理
本行 Chat 内容包括: 简单介绍 IntelliJ IDEA 的安装与注册 什么是 Spring Boot? 如何通过 IDEA 创建一个简单的 Spring Boot 项目 Apache Shi ...
最新文章
- Python进阶8——字典与散列表,字符串编解码
- 设置Eclipse编码方式
- pygame两图层怎么搞_每天解决一个卖酒问题(176):小白怎么开拓市场?
- cometD离线消息
- 回溯算法(Backtracking Algorithm)之八皇后问题
- centos7搭建单机kafka集群
- QT中如何实现Thread与GUI的主线程连通
- python中label怎么绑定变量_Kivy将标签文本绑定到变量(仅限Python)
- 论文笔记--基于 FCM 聚类的跨模态人物图像标注方法-2015
- zoj 3229 Shoot the Bullet(无源汇上下界最大流)
- hibernate could not resolve property
- 判断数组中的元素是否连续
- php做购物商品库存解决方法
- 通过5个概念 一文弄明白DAO
- 数据仓库开发工程师岗位要求
- Java编译环境安装
- 2020牛客暑期多校训练营(第九场) 	The Flee Plan of Groundhog
- Github大文件下载不怕啦
- 有道翻译 爬虫,分析反爬 附代码
- 【SLAM文献】2017-2018 CVPR ICCV ECCV 相机位姿估计、视觉定位、SLAM相关论文综述