天天看点

SpringBoot-Security-用户权限分配-查找用户的菜单权限Spring security认证过程系统权限设计系统权限表结构设计如下查找用户的菜单权限树结构

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

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
}
]