shiro表结构设计_使用 Shiro 设计基于用户、角色、权限的通用权限管理系统

一、前言

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

下面来个 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 login(@Valid User user, BindingResult bindingResult, HttpSession session) {

Map map = new HashMap();

// 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 filterChainDefinitionMap = new LinkedHashMap();

// 配置不会被拦截的链接 顺序判断

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 roles=new HashSet();

List rolesByUserName = roleDao.getRolesByUserName(userName);

for(Role role:rolesByUserName) {

roles.add(role.getRoleName());

}

List 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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值