SpringBoot-Security-用户权限分配-查找用户的菜单权限

简介: 本章实现的功能是,某个用户登录时,如何查找该用户的菜单权限 Spring security认证过程 1、用户使用用户名和密码进行登录。2、Spring Security将获取到的用户名和密码封装成一个实现了Authentication接口的UsernamePasswordAuthenticationToken。

本章实现的功能是,某个用户登录时,如何查找该用户的菜单权限

Spring security认证过程

1、用户使用用户名和密码进行登录。
2、Spring Security将获取到的用户名和密码封装成一个实现了Authentication接口的UsernamePasswordAuthenticationToken。
3、将上述产生的token对象传递给AuthenticationManager进行登录认证。
4、AuthenticationManager认证成功后将会返回一个封装了用户权限等信息的Authentication对象。
5、通过调用SecurityContextHolder.getContext().setAuthentication(...)将AuthenticationManager返回的Authentication对象赋予给当前的SecurityContext。
6、认证成功后,用户就可以继续操作去访问其它受保护的资源了,通过调用SecurityContextHolder.getContext().getAuthentication()获取保存在SecurityContext中的Authentication对象进行相关的权限鉴定。

系统权限设计

设计基础:任何权限的需求,都是为广义的用户分配角色,角色拥有广义的权限。用户、角色、菜单(权限)三大核心表,加上用户角色、角色菜单两个映射表。就可以通过登录的用户来获取权限列表,再间接获取用户菜单列表。

系统权限表结构设计如下

用户表

CREATE TABLE `crm_sys_user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(50) NOT NULL COMMENT '系统用户名',
`password` varchar(60) NOT NULL COMMENT '密码',
`nickname` varchar(255) DEFAULT NULL COMMENT '昵称',
`headImgUrl` varchar(255) DEFAULT NULL COMMENT '头像',
`phone` varchar(11) DEFAULT NULL COMMENT '手机号',
`telephone` varchar(30) DEFAULT NULL COMMENT '电话',
`email` varchar(50) DEFAULT NULL COMMENT '邮箱',
`birthday` varchar(10) DEFAULT NULL COMMENT '生日',
`sex` tinyint(1) DEFAULT NULL COMMENT '性别',
`isEnable` int(1) DEFAULT NULL COMMENT '状态 0.已停用 1.正常',
`isDel` int(1) DEFAULT NULL COMMENT '是否删除(0.已删除 1.正常)',
`createTime` varchar(22) DEFAULT NULL,
`updateTime` varchar(22) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `username` (`username`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COMMENT='系统用户表';

角色表

CREATE TABLE `crm_sys_role` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(50) NOT NULL COMMENT '角色名称',
`description` varchar(100) DEFAULT NULL COMMENT '描述',
`isEnable` tinyint(1) DEFAULT NULL COMMENT '状态 0.已停用 1.正常',
`isDel` tinyint(1) DEFAULT NULL COMMENT '是否删除(0.已删除 1.正常)',
`createTime` varchar(22) DEFAULT NULL,
`updateTime` varchar(22) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `name` (`name`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COMMENT='系统角色表';

菜单表

CREATE TABLE `crm_sys_menu` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`parentId` int(11) NOT NULL COMMENT '上级菜单',
`name` varchar(50) NOT NULL COMMENT '菜单名称',
`css` varchar(30) DEFAULT NULL COMMENT '图标样式',
`href` varchar(1000) DEFAULT NULL COMMENT '链接',
`type` tinyint(1) NOT NULL COMMENT '菜单类型 1:菜单 2:按钮',
`permission` varchar(50) DEFAULT NULL COMMENT '按钮权限',
`sequence` int(11) NOT NULL COMMENT '排序',
`isEnable` int(1) DEFAULT NULL COMMENT '状态 0.已停用 1.正常',
`isDel` int(1) DEFAULT NULL COMMENT '是否删除(0.已删除 1.正常)',
`createTime` varchar(22) DEFAULT NULL,
`updateTime` varchar(22) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=18 DEFAULT CHARSET=utf8mb4 COMMENT='系统菜单表';

用户与角色关联表

CREATE TABLE `crm_sys_user_role` (
`userId` int(11) NOT NULL,
`roleId` int(11) NOT NULL,
PRIMARY KEY (`userId`,`roleId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='系统用户与角色关联表';

角色与菜单关联表

CREATE TABLE `crm_sys_role_menu` (
`roleId` int(11) NOT NULL,
`menuId` int(11) NOT NULL,
PRIMARY KEY (`roleId`,`menuId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='系统角色与菜单关联表';

查找用户的菜单权限树结构

业务代理

@GetMapping("/current")
public List<SysMenuDto> menuCurrent() {
    LoginUser loginUser = UserUtil.getLoginUser();
    Long id = Long.valueOf(String.valueOf(loginUser.getId()));
    List<SysMenuDto> list = iSysMenuService.listByUserId(id);
    final List<SysMenuDto> menus = list.stream().filter(l -> l.getType().equals(1))
            .collect(Collectors.toList());
    //支持多级菜单
    List<SysMenuDto> firstLevel = menus.stream().filter(p -> p.getParentId().equals(0)).collect(Collectors.toList());
    firstLevel.parallelStream().forEach(m -> {
        setChild(m, menus);
    });
    return firstLevel;
}

/**
 * 设置子元素
 * @param m
 * @param menus
 */
private void setChild(SysMenuDto m, List<SysMenuDto> menus) {
    List<SysMenuDto> child = menus.parallelStream().filter(a -> a.getParentId().equals(m.getId())).collect(Collectors.toList());
    m.setChild(child);
    if (!CollectionUtils.isEmpty(child)) {
        child.parallelStream().forEach(c -> {
            //递归设置子元素,多级菜单支持
            setChild(c, menus);
        });
    }
}

Authentication公用类

public class UserUtil {

public static LoginUser getLoginUser() {
    Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
    if (authentication != null) {
        if (authentication instanceof AnonymousAuthenticationToken) {
            return null;
        }

        if (authentication instanceof UsernamePasswordAuthenticationToken) {
            return (LoginUser) authentication.getPrincipal();
        }
    }

    return null;
}

}

sql代码

@Select("select distinct m.* " +
        "from crm_sys_menu m " +
        "inner join crm_sys_role_menu rm on m.id = rm.menuId " +
        "inner join crm_sys_user_role ru on ru.roleId = rm.roleId " +
        "where isDel = 1 and isEnable = 1 and ru.userId = #{userId} order by m.sequence")
List<CrmSysMenuPo> listByUserId(Long userId);

返回结果

[
{
"id": 1,
"parentId": 0,
"name": "系统管理",
"css": "fa-gears",
"href": "",
"type": 1,
"permission": "",
"sequence": 1,
"isEnable": true,
"isDel": true,
"createTime": "2017-10-05 21:59:18",
"child": [
  {
    "id": 2,
    "parentId": 1,
    "name": "用户",
    "css": "fa-users",
    "href": "sys/user/queryList",
    "type": 1,
    "permission": "",
    "sequence": 101,
    "isEnable": true,
    "isDel": true,
    "createTime": "2017-10-05 21:59:18",
    "child": [
      
    ],
    "serialVersion": -123142
  },
  {
    "id": 3,
    "parentId": 1,
    "name": "菜单",
    "css": "fa-cog",
    "href": "sys/menu/queryList",
    "type": 1,
    "permission": "",
    "sequence": 102,
    "isEnable": true,
    "isDel": true,
    "createTime": "2017-10-05 21:59:18",
    "child": [
      
    ],
    "serialVersion": -123142
  },
  {
    "id": 4,
    "parentId": 1,
    "name": "角色",
    "css": "fa-user-secret",
    "href": "sys/role/queryList",
    "type": 1,
    "permission": "",
    "sequence": 103,
    "isEnable": true,
    "isDel": true,
    "createTime": "2017-10-05 21:59:18",
    "child": [
      
    ],
    "serialVersion": -123142
  }
],
"serialVersion": -123142
}
]
目录
相关文章
|
安全 NoSQL Java
SpringBoot3整合SpringSecurity,实现自定义接口权限过滤(二)
SpringBoot3整合SpringSecurity,实现自定义接口权限过滤
896 0
|
2月前
|
JavaScript 安全 Java
【绝密攻略】揭秘Spring Boot与Ant Design Pro Vue的终极结合:打造梦幻般的动态路由与菜单管理,颠覆你的前后端分离世界!
【8月更文挑战第9天】随着前后端分离趋势的发展,构建高效且易维护的框架至关重要。本文介绍如何利用Spring Boot与Ant Design Pro Vue打造带有动态路由和菜单的应用。首先需安装Node.js、NPM及Java开发工具;接着通过Spring Initializr初始化含Web和Security依赖的项目,并配置Spring Security。后端API提供菜单数据,而前端则基于这些数据动态生成路由和菜单。通过具体步骤演示整个流程,包括创建Controller、配置动态路由、设置菜单等。此外还分享了实践心得,强调版本兼容性、安全性等方面的重要性。
96 1
|
4月前
|
JavaScript Java 测试技术
基于springboot+vue.js+uniapp小程序的疫情物资捐赠和分配系统附带文章源码部署视频讲解等
基于springboot+vue.js+uniapp小程序的疫情物资捐赠和分配系统附带文章源码部署视频讲解等
24 0
|
11月前
|
SQL Java 数据库
微服务技术系列教程(39)- SpringBoot -RBAC权限模型
微服务技术系列教程(39)- SpringBoot -RBAC权限模型
173 0
|
5月前
|
存储 安全 前端开发
基于springboot的疫情物资捐赠和分配系统
基于springboot的疫情物资捐赠和分配系统
|
5月前
|
JavaScript 安全 Java
Spring Boot 和 Vue.js 实现的前后端分离的用户权限管理系统
Spring Boot 和 Vue.js 实现的前后端分离的用户权限管理系统
156 0
|
5月前
|
JSON 安全 Java
Springboot最全权限集成Redis-前后端分离-springsecurity-jwt-Token5
Springboot最全权限集成Redis-前后端分离-springsecurity-jwt-Token5
|
5月前
|
Java
Springboot最全权限集成Redis-前后端分离-springsecurity-jwt-Token3
Springboot最全权限集成Redis-前后端分离-springsecurity-jwt-Token3
|
5月前
|
Java
Springboot最全权限集成Redis-前后端分离-springsecurity-jwt-Token4
Springboot最全权限集成Redis-前后端分离-springsecurity-jwt-Token4
|
5月前
|
NoSQL Java Redis
Springboot最全权限集成Redis-前后端分离-springsecurity-jwt-Token4
Springboot最全权限集成Redis-前后端分离-springsecurity-jwt-Token4