赞
踩
RBAC权限模型(Role-Based Access Control)即:基于角色的权限控制。
最经典的五表 RBAC 权限如下:
五张表sql语句:
- CREATE DATABASE /*!32312 IF NOT EXISTS*/`sg_security` /*!40100 DEFAULT CHARACTER SET utf8mb4 */;
-
- USE `sg_security`;
-
- /*Table structure for table `sys_menu` */
-
- DROP TABLE IF EXISTS `sys_menu`;
-
- CREATE TABLE `sys_menu` (
- `id` bigint(20) NOT NULL AUTO_INCREMENT,
- `menu_name` varchar(64) NOT NULL DEFAULT 'NULL' COMMENT '菜单名',
- `path` varchar(200) DEFAULT NULL COMMENT '路由地址',
- `component` varchar(255) DEFAULT NULL COMMENT '组件路径',
- `visible` char(1) DEFAULT '0' COMMENT '菜单状态(0显示 1隐藏)',
- `status` char(1) DEFAULT '0' COMMENT '菜单状态(0正常 1停用)',
- `perms` varchar(100) DEFAULT NULL COMMENT '权限标识',
- `icon` varchar(100) DEFAULT '#' COMMENT '菜单图标',
- `create_by` bigint(20) DEFAULT NULL,
- `create_time` datetime DEFAULT NULL,
- `update_by` bigint(20) DEFAULT NULL,
- `update_time` datetime DEFAULT NULL,
- `del_flag` int(11) DEFAULT '0' COMMENT '是否删除(0未删除 1已删除)',
- `remark` varchar(500) DEFAULT NULL COMMENT '备注',
- PRIMARY KEY (`id`)
- ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COMMENT='菜单表';
-
- /*Table structure for table `sys_role` */
-
- DROP TABLE IF EXISTS `sys_role`;
-
- CREATE TABLE `sys_role` (
- `id` bigint(20) NOT NULL AUTO_INCREMENT,
- `name` varchar(128) DEFAULT NULL,
- `role_key` varchar(100) DEFAULT NULL COMMENT '角色权限字符串',
- `status` char(1) DEFAULT '0' COMMENT '角色状态(0正常 1停用)',
- `del_flag` int(1) DEFAULT '0' COMMENT 'del_flag',
- `create_by` bigint(200) DEFAULT NULL,
- `create_time` datetime DEFAULT NULL,
- `update_by` bigint(200) DEFAULT NULL,
- `update_time` datetime DEFAULT NULL,
- `remark` varchar(500) DEFAULT NULL COMMENT '备注',
- PRIMARY KEY (`id`)
- ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COMMENT='角色表';
-
- /*Table structure for table `sys_role_menu` */
-
- DROP TABLE IF EXISTS `sys_role_menu`;
-
- CREATE TABLE `sys_role_menu` (
- `role_id` bigint(200) NOT NULL AUTO_INCREMENT COMMENT '角色ID',
- `menu_id` bigint(200) NOT NULL DEFAULT '0' COMMENT '菜单id',
- PRIMARY KEY (`role_id`,`menu_id`)
- ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4;
-
- /*Table structure for table `sys_user` */
-
- DROP TABLE IF EXISTS `sys_user`;
-
- CREATE TABLE `sys_user` (
- `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
- `user_name` varchar(64) NOT NULL DEFAULT 'NULL' COMMENT '用户名',
- `nick_name` varchar(64) NOT NULL DEFAULT 'NULL' COMMENT '昵称',
- `password` varchar(64) NOT NULL DEFAULT 'NULL' COMMENT '密码',
- `status` char(1) DEFAULT '0' COMMENT '账号状态(0正常 1停用)',
- `email` varchar(64) DEFAULT NULL COMMENT '邮箱',
- `phonenumber` varchar(32) DEFAULT NULL COMMENT '手机号',
- `sex` char(1) DEFAULT NULL COMMENT '用户性别(0男,1女,2未知)',
- `avatar` varchar(128) DEFAULT NULL COMMENT '头像',
- `user_type` char(1) NOT NULL DEFAULT '1' COMMENT '用户类型(0管理员,1普通用户)',
- `create_by` bigint(20) DEFAULT NULL COMMENT '创建人的用户id',
- `create_time` datetime DEFAULT NULL COMMENT '创建时间',
- `update_by` bigint(20) DEFAULT NULL COMMENT '更新人',
- `update_time` datetime DEFAULT NULL COMMENT '更新时间',
- `del_flag` int(11) DEFAULT '0' COMMENT '删除标志(0代表未删除,1代表已删除)',
- PRIMARY KEY (`id`)
- ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COMMENT='用户表';
-
- /*Table structure for table `sys_user_role` */
-
- DROP TABLE IF EXISTS `sys_user_role`;
-
- CREATE TABLE `sys_user_role` (
- `user_id` bigint(200) NOT NULL AUTO_INCREMENT COMMENT '用户id',
- `role_id` bigint(200) NOT NULL DEFAULT '0' COMMENT '角色id',
- PRIMARY KEY (`user_id`,`role_id`)
- ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
通过 用户id 获取权限标识(即权限模块)
- SELECT
- DISTINCT m.`perms`
- FROM
- sys_user_role ur
- LEFT JOIN `sys_role` r ON ur.`role_id` = r.`id`
- LEFT JOIN `sys_role_menu` rm ON ur.`role_id` = rm.`role_id`
- LEFT JOIN `sys_menu` m ON m.`id` = rm.`menu_id`
- WHERE
- user_id = 2
- AND r.`status` = 0
- AND m.`status` = 0
五张表对应的一个Bean 类:
- public class Menu implements Serializable {
- private static final long serialVersionUID = -54979041104113736L;
-
- @TableId
- private Long id;
- /**
- * 菜单名
- */
- private String menuName;
- /**
- * 路由地址
- */
- private String path;
- /**
- * 组件路径
- */
- private String component;
- /**
- * 菜单状态(0显示 1隐藏)
- */
- private String visible;
- /**
- * 菜单状态(0正常 1停用)
- */
- private String status;
- /**
- * 权限标识
- */
- private String perms;
- /**
- * 菜单图标
- */
- private String icon;
-
- private Long createBy;
-
- private Date createTime;
-
- private Long updateBy;
-
- private Date updateTime;
- /**
- * 是否删除(0未删除 1已删除)
- */
- private Integer delFlag;
- /**
- * 备注
- */
- private String remark;
- }
基础工作准备好后,添加maper,实现mybatisplus查询数据库表权限:
MenuMapper
- public interface MenuMapper extends BaseMapper<Menu> {
-
- List<String> selectPermsByUserId(Long id);
- }
MenuMapper.xml
- <?xml version="1.0" encoding="UTF-8" ?>
- <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
- <mapper namespace="com.frx01.security.mapper.MenuMapper">
- <select id="selectPermsByUserId" resultType="java.lang.String">
- SELECT
- DISTINCT m.`perms`
- FROM
- sys_user_role ur
- LEFT JOIN `sys_role` r ON ur.`role_id` = r.`id`
- LEFT JOIN `sys_role_menu` rm ON ur.`role_id` = rm.`role_id`
- LEFT JOIN `sys_menu` m ON m.`id` = rm.`menu_id`
- WHERE
- user_id = #{userid}
- AND r.`status` = 0
- AND m.`status` = 0
- </select>
- </mapper>
在application.yml中配置mapperXML文件的位置
- mybatis-plus:
- configuration:
- #开启驼峰命名
- map-underscore-to-camel-case: true
- mapper-locations: classpath*:/mapper/*.xml
修改之前的 UserDetailsServiceImpl 类,将手写的 ArrayListg改为从数据库中查询权限
- // 把数据封装成userDetails返回,ArrayList为权限集合,此处作为模拟添加
- // return new LoginUser(user,new ArrayList<>(Arrays.asList("test","admin")));
- // 通过查询数据库,查询出实际用户的权限信息
- List<String> strings = menuMapper.selectPermsByUserId(user.getId());
具体mysql表中的用户权限关系如下:
user表
user_role表
role表
role_menu表
menu表,注意这里的 perms 权限,上面修改的,最终查询的就是这个字段的内容。
修改 LoginController 添加测试接口:
- /**
- * 测试没有abc权限是否可以登录
- * @return
- */
- @GetMapping("/getTest2")
- @PreAuthorize("hasAuthority('system;dept;list')")
- public String getTest2(){
- logger.info("测试没有abc权限是否可以登录");
- return "chenggong";
- }
- /**
- * 测试没有test权限是否可以登录
- * @return
- */
- @GetMapping("/getTest3")
- @PreAuthorize("hasAuthority('system;test;list')")
- public String getTest3(){
- logger.info("测试有test权限是否可以登录");
- return "chenggong";
- }
测试:
使用 fan 用户登录,这里不要忘了复制 jwt 到新的请求接口的 header 中
访问 getTest2,这里的权限不足是因为我添加了自定义处理类,之后会介绍
访问getTest3
至此,从数据库表查询权限判断已完成。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。