当前位置:   article > 正文

SpringSecurity从0到1搭建详细教程三——添加权限RBAC权限模型详解

SpringSecurity从0到1搭建详细教程三——添加权限RBAC权限模型详解

RBAC权限模型

RBAC权限模型(Role-Based Access Control)即:基于角色的权限控制

最经典的五表 RBAC 权限如下:

五张表sql语句:

  1. CREATE DATABASE /*!32312 IF NOT EXISTS*/`sg_security` /*!40100 DEFAULT CHARACTER SET utf8mb4 */;
  2. USE `sg_security`;
  3. /*Table structure for table `sys_menu` */
  4. DROP TABLE IF EXISTS `sys_menu`;
  5. CREATE TABLE `sys_menu` (
  6. `id` bigint(20) NOT NULL AUTO_INCREMENT,
  7. `menu_name` varchar(64) NOT NULL DEFAULT 'NULL' COMMENT '菜单名',
  8. `path` varchar(200) DEFAULT NULL COMMENT '路由地址',
  9. `component` varchar(255) DEFAULT NULL COMMENT '组件路径',
  10. `visible` char(1) DEFAULT '0' COMMENT '菜单状态(0显示 1隐藏)',
  11. `status` char(1) DEFAULT '0' COMMENT '菜单状态(0正常 1停用)',
  12. `perms` varchar(100) DEFAULT NULL COMMENT '权限标识',
  13. `icon` varchar(100) DEFAULT '#' COMMENT '菜单图标',
  14. `create_by` bigint(20) DEFAULT NULL,
  15. `create_time` datetime DEFAULT NULL,
  16. `update_by` bigint(20) DEFAULT NULL,
  17. `update_time` datetime DEFAULT NULL,
  18. `del_flag` int(11) DEFAULT '0' COMMENT '是否删除(0未删除 1已删除)',
  19. `remark` varchar(500) DEFAULT NULL COMMENT '备注',
  20. PRIMARY KEY (`id`)
  21. ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COMMENT='菜单表';
  22. /*Table structure for table `sys_role` */
  23. DROP TABLE IF EXISTS `sys_role`;
  24. CREATE TABLE `sys_role` (
  25. `id` bigint(20) NOT NULL AUTO_INCREMENT,
  26. `name` varchar(128) DEFAULT NULL,
  27. `role_key` varchar(100) DEFAULT NULL COMMENT '角色权限字符串',
  28. `status` char(1) DEFAULT '0' COMMENT '角色状态(0正常 1停用)',
  29. `del_flag` int(1) DEFAULT '0' COMMENT 'del_flag',
  30. `create_by` bigint(200) DEFAULT NULL,
  31. `create_time` datetime DEFAULT NULL,
  32. `update_by` bigint(200) DEFAULT NULL,
  33. `update_time` datetime DEFAULT NULL,
  34. `remark` varchar(500) DEFAULT NULL COMMENT '备注',
  35. PRIMARY KEY (`id`)
  36. ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COMMENT='角色表';
  37. /*Table structure for table `sys_role_menu` */
  38. DROP TABLE IF EXISTS `sys_role_menu`;
  39. CREATE TABLE `sys_role_menu` (
  40. `role_id` bigint(200) NOT NULL AUTO_INCREMENT COMMENT '角色ID',
  41. `menu_id` bigint(200) NOT NULL DEFAULT '0' COMMENT '菜单id',
  42. PRIMARY KEY (`role_id`,`menu_id`)
  43. ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4;
  44. /*Table structure for table `sys_user` */
  45. DROP TABLE IF EXISTS `sys_user`;
  46. CREATE TABLE `sys_user` (
  47. `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
  48. `user_name` varchar(64) NOT NULL DEFAULT 'NULL' COMMENT '用户名',
  49. `nick_name` varchar(64) NOT NULL DEFAULT 'NULL' COMMENT '昵称',
  50. `password` varchar(64) NOT NULL DEFAULT 'NULL' COMMENT '密码',
  51. `status` char(1) DEFAULT '0' COMMENT '账号状态(0正常 1停用)',
  52. `email` varchar(64) DEFAULT NULL COMMENT '邮箱',
  53. `phonenumber` varchar(32) DEFAULT NULL COMMENT '手机号',
  54. `sex` char(1) DEFAULT NULL COMMENT '用户性别(0男,1女,2未知)',
  55. `avatar` varchar(128) DEFAULT NULL COMMENT '头像',
  56. `user_type` char(1) NOT NULL DEFAULT '1' COMMENT '用户类型(0管理员,1普通用户)',
  57. `create_by` bigint(20) DEFAULT NULL COMMENT '创建人的用户id',
  58. `create_time` datetime DEFAULT NULL COMMENT '创建时间',
  59. `update_by` bigint(20) DEFAULT NULL COMMENT '更新人',
  60. `update_time` datetime DEFAULT NULL COMMENT '更新时间',
  61. `del_flag` int(11) DEFAULT '0' COMMENT '删除标志(0代表未删除,1代表已删除)',
  62. PRIMARY KEY (`id`)
  63. ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COMMENT='用户表';
  64. /*Table structure for table `sys_user_role` */
  65. DROP TABLE IF EXISTS `sys_user_role`;
  66. CREATE TABLE `sys_user_role` (
  67. `user_id` bigint(200) NOT NULL AUTO_INCREMENT COMMENT '用户id',
  68. `role_id` bigint(200) NOT NULL DEFAULT '0' COMMENT '角色id',
  69. PRIMARY KEY (`user_id`,`role_id`)
  70. ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

通过 用户id 获取权限标识(即权限模块)

  1. SELECT
  2. DISTINCT m.`perms`
  3. FROM
  4. sys_user_role ur
  5. LEFT JOIN `sys_role` r ON ur.`role_id` = r.`id`
  6. LEFT JOIN `sys_role_menu` rm ON ur.`role_id` = rm.`role_id`
  7. LEFT JOIN `sys_menu` m ON m.`id` = rm.`menu_id`
  8. WHERE
  9. user_id = 2
  10. AND r.`status` = 0
  11. AND m.`status` = 0

五张表对应的一个Bean 类:

  1. public class Menu implements Serializable {
  2. private static final long serialVersionUID = -54979041104113736L;
  3. @TableId
  4. private Long id;
  5. /**
  6. * 菜单名
  7. */
  8. private String menuName;
  9. /**
  10. * 路由地址
  11. */
  12. private String path;
  13. /**
  14. * 组件路径
  15. */
  16. private String component;
  17. /**
  18. * 菜单状态(0显示 1隐藏)
  19. */
  20. private String visible;
  21. /**
  22. * 菜单状态(0正常 1停用)
  23. */
  24. private String status;
  25. /**
  26. * 权限标识
  27. */
  28. private String perms;
  29. /**
  30. * 菜单图标
  31. */
  32. private String icon;
  33. private Long createBy;
  34. private Date createTime;
  35. private Long updateBy;
  36. private Date updateTime;
  37. /**
  38. * 是否删除(0未删除 1已删除)
  39. */
  40. private Integer delFlag;
  41. /**
  42. * 备注
  43. */
  44. private String remark;
  45. }

基础工作准备好后,添加maper,实现mybatisplus查询数据库表权限:

MenuMapper

  1. public interface MenuMapper extends BaseMapper<Menu> {
  2. List<String> selectPermsByUserId(Long id);
  3. }

MenuMapper.xml

  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
  3. <mapper namespace="com.frx01.security.mapper.MenuMapper">
  4. <select id="selectPermsByUserId" resultType="java.lang.String">
  5. SELECT
  6. DISTINCT m.`perms`
  7. FROM
  8. sys_user_role ur
  9. LEFT JOIN `sys_role` r ON ur.`role_id` = r.`id`
  10. LEFT JOIN `sys_role_menu` rm ON ur.`role_id` = rm.`role_id`
  11. LEFT JOIN `sys_menu` m ON m.`id` = rm.`menu_id`
  12. WHERE
  13. user_id = #{userid}
  14. AND r.`status` = 0
  15. AND m.`status` = 0
  16. </select>
  17. </mapper>

在application.yml中配置mapperXML文件的位置

  1. mybatis-plus:
  2. configuration:
  3. #开启驼峰命名
  4. map-underscore-to-camel-case: true
  5. mapper-locations: classpath*:/mapper/*.xml

修改之前的 UserDetailsServiceImpl 类,将手写的 ArrayListg改为从数据库中查询权限

  1. // 把数据封装成userDetails返回,ArrayList为权限集合,此处作为模拟添加
  2. // return new LoginUser(user,new ArrayList<>(Arrays.asList("test","admin")));
  3. // 通过查询数据库,查询出实际用户的权限信息
  4. List<String> strings = menuMapper.selectPermsByUserId(user.getId());

具体mysql表中的用户权限关系如下:

user表 

user_role表 

role表

 role_menu表

menu表,注意这里的 perms 权限,上面修改的,最终查询的就是这个字段的内容。

 修改  LoginController 添加测试接口:

  1. /**
  2. * 测试没有abc权限是否可以登录
  3. * @return
  4. */
  5. @GetMapping("/getTest2")
  6. @PreAuthorize("hasAuthority('system;dept;list')")
  7. public String getTest2(){
  8. logger.info("测试没有abc权限是否可以登录");
  9. return "chenggong";
  10. }
  11. /**
  12. * 测试没有test权限是否可以登录
  13. * @return
  14. */
  15. @GetMapping("/getTest3")
  16. @PreAuthorize("hasAuthority('system;test;list')")
  17. public String getTest3(){
  18. logger.info("测试有test权限是否可以登录");
  19. return "chenggong";
  20. }

测试:

 ​​​​​​使用 fan 用户登录,这里不要忘了复制 jwt 到新的请求接口的 header 中

 访问 getTest2,这里的权限不足是因为我添加了自定义处理类,之后会介绍

访问getTest3

 至此,从数据库表查询权限判断已完成。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/436973
推荐阅读
相关标签
  

闽ICP备14008679号