系列文章目录
《SpringBoot整合SpringSecurity实现权限控制(一):实现原理》
《SpringBoot整合SpringSecurity实现权限控制(二):权限数据基本模型设计》
《SpringBoot整合SpringSecurity实现权限控制(三):前端动态装载路由与菜单》
《SpringBoot整合SpringSecurity实现权限控制(四):角色管理》
《SpringBoot整合SpringSecurity实现权限控制(五):用户管理》
《SpringBoot整合SpringSecurity实现权限控制(六):菜单管理》
本文目录
一、实现原理
- 在前面的系列文章中,我们已经实现了用户管理、角色管理与菜单管理,接下来我们把这三个功能串起来:
- 通过权限分配把让角色关联到各个功能菜单。比如让系统管理员角色关联到用户管理、角色管理等菜单。
- 通过角色设置让用户关联到单个或多个角色。比如让张三用户关联到系统管理员角色。
- 用户关联到角色,角色关联到菜单,也即让用户间接拥有了系统的功能。
二、后端实现
2.1 创建权限表
- 该表存储角色id与菜单id的关联信息
/**
* 权限表
*
* @author zhuhuix
* @date 2021-10-26
*/
@ApiModel(value = "权限信息")
@Data
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
@TableName("sys_permission")
public class SysPermission {
@TableId(value = "id", type = IdType.AUTO)
private Long id;
// 角色id
private Long roleId;
// 菜单id
private Long menuId;
private Timestamp createTime;
public SysPermission(Long roleId, Long menuId, Timestamp createTime) {
this.roleId = roleId;
this.menuId = menuId;
this.createTime = createTime;
}
}
2.2 添加操作权限表的Mapper接口
- 通过继承mybatis-plus的BaseMapper接口创建操作权限表的DAO接口,该BaseMapper接口已经包含了基本的增删改查操作。
/**
* 权限表DAO接口
*
* @author zhuhuix
* @date 2021-10-26
*/
@Mapper
public interface SysPermissionMapper extends BaseMapper<SysPermission> {
// BaseMapper接口已经默认实现了基本的增删改查操作
}
2.3 实现角色权限分配的服务
- 在原有角色管理的服务接口中加入获取角色权限与保存角色权限的接口.
/**
* 角色信息接口
*
* @author zhuhuix
* @date 2021-09-13
* @date 2021-10-26 增加getPermission,savePermission
*/
public interface SysRoleService {
....
/**
* 获取角色权限
*
* @param roleId 角色id
* @return 角色权限列表
*/
List<SysPermission> getPermission(Long roleId);
/**
* 保存角色权限
*
* @param roleId 角色id
* @param menus 权限表
* @return 是否成功
*/
Boolean savePermission(Long roleId,Set<Long> menus);
}
- 实现获取角色权限与保存角色权限的接口
/**
* 角色实现类
*
* @author zhuhuix
* @date 2021-09-13
* @date 2021-10-26 实现getPermission,savePermission接口
*/
@Slf4j
@Service
@RequiredArgsConstructor
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class SysRoleServiceImpl implements SysRoleService {
private final SysRoleMapper sysRoleMapper;
private final SysPermissionMapper sysPermissionMapper;
...
@Override
public List<SysPermission> getPermission(Long roleId) {
QueryWrapper<SysPermission> queryWrapper = new QueryWrapper<>();
queryWrapper.lambda().eq(SysPermission::getRoleId, roleId);
return sysPermissionMapper.selectList(queryWrapper);
}
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean savePermission(Long roleId, Set<Long> menus) {
// 先根据roleId删除原有权限
QueryWrapper<SysPermission> queryWrapper = new QueryWrapper<>();
queryWrapper.lambda().eq(SysPermission::getRoleId, roleId);
sysPermissionMapper.delete(queryWrapper);
// 再插入roleId新权限
for (Long menu : menus) {
int rowCount = sysPermissionMapper.insert(
new SysPermission(roleId, menu, Timestamp.valueOf(LocalDateTime.now())));
if (rowCount <= 0) {
throw new RuntimeException("保存权限失败");
}
}
return true;
}
}
2.4 在Controller层添加访问API接口
/**
* 角色信息api
*
* @author zhuhuix
* @date 2021-09-13
* @date 2021-10-26 增加getPermission,savePermission API接口
*/
@Slf4j
@RestController
@AllArgsConstructor
@RequestMapping("/api/role")
@Api(tags = "角色信息接口")
public class SysRoleController {
private final SysRoleService sysRoleService;
....
@ApiOperation("获取角色权限信息")
@GetMapping("{roleId}/permission")
public ResponseEntity<Object> getPermission(@PathVariable Long roleId) {
return ResponseEntity.ok(sysRoleService.getPermission(roleId));
}
@ApiOperation("保存角色权限信息")
@PostMapping("{roleId}/permission")
public ResponseEntity<Object> savePermission(@PathVariable Long roleId,@RequestBody Set<Long> menus) {
return ResponseEntity.ok(sysRoleService.savePermission(roleId,menus));
}
}
三、前端实现
3.1 添加角色权限api访问接口
- 根据后端API,在角色信息api访问中添加读取权限与保存权限的接口
/**
* 角色访问后端api
* 2021-10-26 添加getPermission,savePermission
*/
import request from '@/utils/request'
...
export function getPermission(roleId) {
return request({
url: '/api/role/' + roleId + '/permission',
method: 'get'
})
}
export function savePermission(roleId, data) {
return request({
url: '/api/role/' + roleId + '/permission',
method: 'post',
data
})
}
3.2 添加角色分配权限的页面
- 我们需要在原有角色信息的卡片列表中增加分配权限的按钮,用户点击按钮后弹出对应角色分配权限的操作页面。
- 在弹出的操作页面上引用TreeSelect组件,加载系统的功能菜单,供用户选择。
- 权限分配页面的完整实现代码
/**
* role/index.vue
* 2021-10-27 增加角色权限分配操作页面
*/
<template>
<div class="app-container">
<!--工具栏-->
<div class="head-container">
<!-- 搜索 -->
<el-input
v-model="roleName"
size="small"
clearable
placeholder="输入角色名称搜索"
style="width: 200px"
class="filter-item"
@keyup.enter.native="doQuery"
/>
<el-date-picker
v-model="createTime"
:default-time="['00:00:00', '23:59:59']"
type="daterange"
range-separator=":"
size="small"
class="date-item"
value-format="yyyy-MM-dd HH:mm:ss"
start-placeholder="开始日期"
end-placeholder="结束日期"
/>
<el-button
class="filter-item"
size="mini"
type="success"
icon="el-icon-search"
@click="doQue