一、前言

在大型的信息管理系统中,经常涉及到权限管理系统

下面来个 demo,很多复杂的系统的设计都来自它

代码已经放到github上了,地址:https://github.com/larger5/shiro_urp.git

2018.4.3 版本0.5 在 SpringBoot 中使用 Shiro+MySQL 做登录拦截

2018.4.6 版本1.0 使用 Shiro 设计基于用户、角色、权限的通用权限管理系统

以后继续更新,如用户、角色、权限 CRUD 等,真正做到所谓的权限管理系统

二、数据库表的设计

下面使用 SpringBoot + JPA 的,自动生成如下的表

用户角色多对多、角色权限多对多,设计一个通用的权限系统(无论初衷是一个用户多个角色还是一个角色)

三、效果

说明:

①UI:

  使用了 LayUI 简单优化一下界面

②角色所含权限:

   p:select
ip:select、insert
vip:select、insert、update、delete

③权限:

   select
insert
update
delete

以使用 itaem (VIP)为例

图解:

有:① select、insert、update、delete 权限 ② vip 角色

无:ip角色、p角色,点击后都是没有反应的

四、代码(github 平台上看)

① Controller(重点)

package com.cun.controller;

import java.util.HashMap;
import java.util.Map; import javax.servlet.http.HttpSession;
import javax.validation.Valid; import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.apache.shiro.subject.Subject;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import com.cun.entity.User; import springfox.documentation.swagger2.annotations.EnableSwagger2; @EnableSwagger2
@RestController
@RequestMapping("/user")
public class UserController { @PostMapping("/login")
public Map<String, Object> login(@Valid User user, BindingResult bindingResult, HttpSession session) {
Map<String, Object> map = new HashMap<String, Object>(); // 1、JSR303
if (bindingResult.hasErrors()) {
map.put("success", false);
map.put("errorInfo", bindingResult.getFieldError().getDefaultMessage());
return map;
} // 2、Shiro
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken(user.getUserName(), user.getPassword());
try {
subject.login(token);
map.put("success", true);
return map;
} catch (Exception e) {
e.printStackTrace();
map.put("success", false);
map.put("errorInfo", "用户名或者密码错误!");
return map;
}
}

④ ShiroConfig(重点)

package com.cun.config;

import java.util.LinkedHashMap;
import java.util.Map; 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.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.apache.shiro.mgt.SecurityManager;
import com.cun.realm.MyRealm; /**
* Shiro配置类
* @author linhongcun
*
*/
@Configuration
public class ShiroConfig {
/**
* ShiroFilterFactoryBean 处理拦截资源文件问题。
* 注意:单独一个ShiroFilterFactoryBean配置是或报错的,以为在
* 初始化ShiroFilterFactoryBean的时候需要注入:SecurityManager
*
* Filter Chain定义说明 1、一个URL可以配置多个Filter,使用逗号分隔 2、当设置多个过滤器时,全部验证通过,才视为通过
* 3、部分过滤器可指定参数,如perms,roles
*
*/
@Bean
public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); // 必须设置 SecurityManager
shiroFilterFactoryBean.setSecurityManager(securityManager); // 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面
shiroFilterFactoryBean.setLoginUrl("/login.html"); // 拦截器.
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
// 配置不会被拦截的链接 顺序判断
filterChainDefinitionMap.put("/static/**", "anon");
filterChainDefinitionMap.put("/user/login", "anon");
//测试权限用
filterChainDefinitionMap.put("/swagger-ui.html", "anon"); // 配置退出过滤器,其中的具体的退出代码Shiro已经替我们实现了
filterChainDefinitionMap.put("/logout", "logout"); // 过滤链定义,从上向下顺序执行,一般将 /**放在最为下边 :这是一个坑呢,一不小心代码就不好使了;
// ① authc:所有url都必须认证通过才可以访问; ② anon:所有url都都可以匿名访问
filterChainDefinitionMap.put("/**", "authc");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryBean;
} @Bean
public SecurityManager securityManager() {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
// 设置realm.
securityManager.setRealm(myRealm());
return securityManager;
} /**
* 身份认证realm; (这个需要自己写,账号密码校验;权限等)
*
* @return
*/
@Bean
public MyRealm myRealm() {
MyRealm myRealm = new MyRealm();
return myRealm;
} /**
* Shiro生命周期处理器
* @return
*/
@Bean
public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
return new LifecycleBeanPostProcessor();
} /**
* 开启Shiro的注解(如@RequiresRoles,@RequiresPermissions),需借助SpringAOP扫描使用Shiro注解的类,并在必要时进行安全逻辑验证
* 配置以下两个bean(DefaultAdvisorAutoProxyCreator(可选)和AuthorizationAttributeSourceAdvisor)即可实现此功能
* @return
*/
@Bean
@DependsOn({ "lifecycleBeanPostProcessor" })
public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator() {
DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
advisorAutoProxyCreator.setProxyTargetClass(true);
return advisorAutoProxyCreator;
} @Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor() {
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager());
return authorizationAttributeSourceAdvisor;
}
}

⑤ MyRealm(重点)

package com.cun.realm;

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.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired; import com.cun.dao.PermissionDao;
import com.cun.dao.RoleDao;
import com.cun.dao.UserDao;
import com.cun.entity.Permission;
import com.cun.entity.Role;
import com.cun.entity.User; public class MyRealm extends AuthorizingRealm { @Autowired
private UserDao userDao; @Autowired
private RoleDao roleDao; @Autowired
private PermissionDao permissionDao; /**
* 授权
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
String userName=(String) SecurityUtils.getSubject().getPrincipal();
SimpleAuthorizationInfo info=new SimpleAuthorizationInfo();
Set<String> roles=new HashSet<String>();
List<Role> rolesByUserName = roleDao.getRolesByUserName(userName);
for(Role role:rolesByUserName) {
roles.add(role.getRoleName());
}
List<Permission> permissionsByUserName = permissionDao.getPermissionsByUserName(userName);
for(Permission permission:permissionsByUserName) {
info.addStringPermission(permission.getPermissionName());
}
info.setRoles(roles);
return info;
} /**
* 认证
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
System.out.println("token.getPrincipal:" + token.getPrincipal());
System.out.println("token.getCredentials:" + token.getCredentials());
String userName = token.getPrincipal().toString();
User user = userDao.getUserByUserName(userName);
if (user != null) {
// Object principal, Object credentials, String realmName
AuthenticationInfo authcInfo = new SimpleAuthenticationInfo(user.getUserName(), user.getPassword(), getName());
return authcInfo;
} else {
return null;
}
} }

五、其他

① sql

CREATE DATABASE /*!32312 IF NOT EXISTS*/`urp` /*!40100 DEFAULT CHARACTER SET utf8 */;

USE `urp`;

/*Table structure for table `t_permission` */

DROP TABLE IF EXISTS `t_permission`;

CREATE TABLE `t_permission` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`permission_name` varchar(50) DEFAULT NULL,
`remarks` varchar(1000) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8; /*Data for the table `t_permission` */ insert into `t_permission`(`id`,`permission_name`,`remarks`) values (1,'select','查询'),(2,'insert','增加'),(3,'update','更新'),(4,'delete','删除'); /*Table structure for table `t_role` */ DROP TABLE IF EXISTS `t_role`; CREATE TABLE `t_role` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`remarks` varchar(1000) DEFAULT NULL,
`role_name` varchar(100) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8; /*Data for the table `t_role` */ insert into `t_role`(`id`,`remarks`,`role_name`) values (1,'普通角色','p'),(2,'重要角色','ip'),(3,'超级角色','vip'); /*Table structure for table `t_role_permission` */ DROP TABLE IF EXISTS `t_role_permission`; CREATE TABLE `t_role_permission` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`remarks` varchar(1000) DEFAULT NULL,
`permission_id` int(11) DEFAULT NULL,
`role_id` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `FKjobmrl6dorhlfite4u34hciik` (`permission_id`),
KEY `FK90j038mnbnthgkc17mqnoilu9` (`role_id`),
CONSTRAINT `FK90j038mnbnthgkc17mqnoilu9` FOREIGN KEY (`role_id`) REFERENCES `t_role` (`id`),
CONSTRAINT `FKjobmrl6dorhlfite4u34hciik` FOREIGN KEY (`permission_id`) REFERENCES `t_permission` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8; /*Data for the table `t_role_permission` */ insert into `t_role_permission`(`id`,`remarks`,`permission_id`,`role_id`) values (1,'授予普通角色select权限',1,1),(2,'授予重要角色select权限',1,2),(3,'授予重要角色insert权限',2,2),(4,'授予超级角色select权限',1,3),(5,'授予超级角色insert权限',2,3),(6,'授予超级角色update权限',3,3),(7,'授予超级角色delete权限',4,3); /*Table structure for table `t_user` */ DROP TABLE IF EXISTS `t_user`; CREATE TABLE `t_user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`password` varchar(100) NOT NULL,
`remarks` varchar(1000) DEFAULT NULL,
`user_name` varchar(100) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8; /*Data for the table `t_user` */ insert into `t_user`(`id`,`password`,`remarks`,`user_name`) values (1,'123','JKing团队','jking'),(2,'123','网维团队','wteam'),(3,'123','ITAEM团队','itaem'); /*Table structure for table `t_user_role` */ DROP TABLE IF EXISTS `t_user_role`; CREATE TABLE `t_user_role` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`remarks` varchar(1000) DEFAULT NULL,
`role_id` int(11) DEFAULT NULL,
`user_id` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `FKa9c8iiy6ut0gnx491fqx4pxam` (`role_id`),
KEY `FKq5un6x7ecoef5w1n39cop66kl` (`user_id`),
CONSTRAINT `FKq5un6x7ecoef5w1n39cop66kl` FOREIGN KEY (`user_id`) REFERENCES `t_user` (`id`),
CONSTRAINT `FKa9c8iiy6ut0gnx491fqx4pxam` FOREIGN KEY (`role_id`) REFERENCES `t_role` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8; /*Data for the table `t_user_role` */ insert into `t_user_role`(`id`,`remarks`,`role_id`,`user_id`) values (1,'授予JKing团队普通角色',1,1),(2,'授予网维团队重要角色',2,2),(3,'授予ITAEM团队超级角色',3,3);

转载https://blog.csdn.net/larger5/article/details/79838212

使用 Shiro 设计基于用户、角色、权限的通用权限管理系统的更多相关文章

  1. 基于SSM框架的JavaWeb通用权限管理系统

    - - ->关注博主公众号[C you again],获取更多IT资源(IT技术文章,毕业设计.课程设计系统源码,经典游戏源码,HTML网页模板,PPT.简历模板,!!还可以投稿赚钱!!,点击查 ...

  2. 基于Extjs 4.2的通用权限管理系统,通用后台模板,EF+MVC+Extjs 4.2

    基于Extjs 4.2的通用权限管理系统,通用后台. 我们的宗旨:珍爱生命,拒绝重复!Don't Repeat Yourself!!! 本案例采用EntityFramework+MVC4.0+Extj ...

  3. 分享基于EF+MVC+Bootstrap的通用后台管理系统及架构

      基于EF+MVC+Bootstrap构建通用后台管理系统,集成轻量级的缓存模块.日志模块.上传缩略图模块.通用配置及服务调用, 提供了OA.CRM.CMS的原型实例,适合快速构建中小型互联网及行业 ...

  4. 分享基于EF+MVC+Bootstrap的通用后台管理系统及架构(转)

    http://www.cnblogs.com/guozili/p/3496265.html 基于EF+MVC+Bootstrap构建通用后台管理系统,集成轻量级的缓存模块.日志模块.上传缩略图模块.通 ...

  5. 基于EF+MVC+Bootstrap的通用后台管理系统及架构

    分享基于EF+MVC+Bootstrap的通用后台管理系统及架构 基于EF+MVC+Bootstrap构建通用后台管理系统,集成轻量级的缓存模块.日志模块.上传缩略图模块.通用配置及服务调用, 提供了 ...

  6. Creating adaptive web recommendation system based on user behavior(设计基于用户行为数据的适应性网络推荐系统)

    文章介绍了一个基于用户行为数据的推荐系统的实现步骤和方法.系统的核心是专家系统,它会根据一定的策略计算所有物品的相关度,并且将相关度最高的物品序列推送给用户.计算相关度的策略分为两部分,第一部分是针对 ...

  7. 课程设计-基于SSM的美容美发造型预约管理系统代码Java理发剪发设计造型系统vue美发店管理系统

    注意:该项目只展示部分功能,如需了解,评论区咨询即可. 1.开发环境 开发语言:Java 后台框架:SSM 前端框架:vue 数据库:MySQL 设计模式:MVC 架构:B/S 源码类型: Web 编 ...

  8. jeesite快速开发平台(五)----用户-角色-部门-区域-菜单-权限表关系

    转自: https://blog.csdn.net/u011781521/article/details/78994904

  9. SpringBoot整合Shiro实现基于角色的权限访问控制(RBAC)系统简单设计从零搭建

    SpringBoot整合Shiro实现基于角色的权限访问控制(RBAC)系统简单设计从零搭建 技术栈 : SpringBoot + shiro + jpa + freemark ,因为篇幅原因,这里只 ...

随机推荐

  1. spring cloud(一) 副 consul

    spring cloud 使用consul作为注册中心 1.安装consul 使用docker安装 查找consul镜像 docker search consul 下载镜像 docker pull c ...

  2. 05 Django与Ajax

      一.Ajax简介 AJAX(Asynchronous Javascript And XML)翻译成中文就是“异步Javascript和XML”.即使用Javascript语言与服务器进行异步交互, ...

  3. spring boot-- 三种启动方式

    spring-boot的三种启动方式 1. 直接运行SpringbootApplication.java 2.在项目目录下运行mvn spring-boot:run 3.先编译项目mvn instal ...

  4. Oracle 知识积累

    1.oracle存储过程中is和as的区别 在存储过程(PROCEDURE)和函数(FUNCTION)中没有区别,在视图(VIEW)中只能用AS不能用IS,在游标(CURSOR)中只能用IS不能用AS ...

  5. InitializingBean 和 DisposableBean 指定初始化和销毁方法

    通过实现 InitializingBean 和 DisposableBean 接口,也可以指定 bean 的初始化和销毁方法 二.Student 类 public class Student impl ...

  6. HDU 4342

    先确定M的大致范围后即可求. #include <iostream> #include <cstdio> #include <algorithm> #include ...

  7. NEFU 84

    其实同POJ 1061 #include <iostream> #include <cstdio> #include <cstring> #include < ...

  8. 八皇后问题java实现

    八皇后问题java实现 public class eightqueen { public static int count=0; public static void main(String[] ar ...

  9. CSDN高校俱乐部第二届战神杯第二题题解

    两个人玩一个数字游戏,给定两个正整数A,B,两个人轮流从一个数中减去另外一个数的正数倍.要保证结果非负, 首先得到0的人获胜. 比如:30 8经过一步操作能够变为22 8 或者14 8 或者 6 8. ...

  10. J2SE基础:10集合2

    2:列表(List) 特点: (1):有序的(插入的顺序有序),元素有索引值. (2):同意反复. set/get/listIterator/subList ArrayList 特点:(1):底层数组 ...