博学谷-基于SaaS平台的iHRM实战开发05-权限分配与jwt概述第五天

第4章 权限管理与jwt鉴权

最后附上视频下载地址

学习目标:
理解权限管理的需求以及设计思路
实现角色分配和权限分配
理解常见的认证机制
能够使用JWT完成微服务Token签发与验证


1 权限管理


1.1 需求分析


完成权限(菜单,按钮(权限点),API接口)的基本操作

博学谷-基于SaaS平台的iHRM实战开发05-权限分配与jwt概述第五天

权限与菜单,菜单与按钮,菜单与API接口都是一对一关系。为了方便操作,在SAAS-HRM系统的表设计中,采用
基于共享主键的形式实现一对一关系维护,并且数据库约束,一切的关系维护需要程序员在代码中实现。


1.2 后端实现


1.2.1 实体类
在系统微服务中创建权限,菜单,按钮(权限点),API对象的实体类
(1) 权限实体类Permission
@Entity
@Table(name = "pe_permission")
@Getter
@Setter
@NoArgsConstructor
@DynamicInsert(true)
@DynamicUpdate(true)
public class Permission implements Serializable {
private static final long serialVersionUID = -4990810027542971546L;
/**
* 主键
*/
@Id
private String id;
/**
* 权限名称
*/
private String name;
/**
* 权限类型 1为菜单 2为功能 3为API
*/
private Integer type;
/**
* 权限编码
*/
private String code;
/**
* 权限描述
*/
private String description;
private String pid;
//可见状态
private String enVisible;
public Permission(String name, Integer type, String code, String description) {
this.name = name;
this.type = type;
this.code = code;
this.description = description;
}
}

(2)权限菜单实体类PermissionMenu
@Entity
@Table(name = "pe_permission_menu")
@Getter
@Setter
public class PermissionMenu implements Serializable {
private static final long serialVersionUID = -1002411490113957485L;
@Id
private String id; //主键
private String menuIcon; //展示图标
private String menuOrder; //排序号
}

(3)权限菜单(权限点)实体类PermissionPoint
@Entity
@Table(name = "pe_permission_point")
@Getter
@Setter
public class PermissionPoint implements Serializable {
private static final long serialVersionUID = -1002411490113957485L;
@Id
private String id;
private String pointClass;
private String pointIcon;
private String pointStatus;
}

(4)权限API实体类PermissionApi
@Entity
@Table(name = "pe_permission_api")
@Getter
@Setter
public class PermissionApi implements Serializable {
private static final long serialVersionUID = -1803315043290784820L;
@Id
private String id;
private String apiUrl;
private String apiMethod;
private String apiLevel;//权限等级,1为通用接口权限,2为需校验接口权限
}

1.2.2 持久层
(1)权限持久化类
/**
* 权限数据访问接口
*/
public interface PermissionDao extends JpaRepository<Permission, String>,
JpaSpecificationExecutor<Permission> {
List<Permission> findByTypeAndPid(int type,String pid);
}

(2)权限菜单持久化类
public interface PermissionMenuDao extends JpaRepository<PermissionMenu, String>,
JpaSpecificationExecutor<PermissionMenu> {
}

(3)权限按钮(点)持久化类
public interface PermissionPointDao extends JpaRepository<PermissionPoint, String>,
JpaSpecificationExecutor<PermissionPoint> {
}

(4)权限API持久化类
public interface PermissionApiDao extends JpaRepository<PermissionApi, String>,
JpaSpecificationExecutor<PermissionApi> {
}

1.2.3 业务逻辑
package com.ihrm.system.service;
import com.ihrm.common.entity.ResultCode;
import com.ihrm.common.exception.CommonException;
import com.ihrm.common.utils.BeanMapUtils;
import com.ihrm.common.utils.IdWorker;
import com.ihrm.common.utils.PermissionConstants;
import com.ihrm.domain.system.*;
import com.ihrm.system.dao.*;
import com.ihrm.system.dao.PermissionDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@Service
@Transactional
public class PermissionService {
@Autowired
private PermissionDao permissionDao;
@Autowired
private PermissionMenuDao permissionMenuDao;
@Autowired
private PermissionPointDao permissionPointDao;
@Autowired
private PermissionApiDao permissionApiDao;
@Autowired
private IdWorker idWorker;
/**
* 1.保存权限
*/
public void save(Map<String,Object> map) throws Exception {
//设置主键的值
String id = idWorker.nextId()+"";
//1.通过map构造permission对象
Permission perm = BeanMapUtils.mapToBean(map,Permission.class);
perm.setId(id);
//2.根据类型构造不同的资源对象(菜单,按钮,api)
int type = perm.getType();
switch (type) {
case PermissionConstants.PERMISSION_MENU:
PermissionMenu menu = BeanMapUtils.mapToBean(map,PermissionMenu.class);
menu.setId(id);
permissionMenuDao.save(menu);
break;
case PermissionConstants.PERMISSION_POINT:
PermissionPoint point =
BeanMapUtils.mapToBean(map,PermissionPoint.class);
point.setId(id);
permissionPointDao.save(point);
break;
case PermissionConstants.PERMISSION_API:
PermissionApi api = BeanMapUtils.mapToBean(map,PermissionApi.class);
api.setId(id);
permissionApiDao.save(api);
break;
default:
throw new CommonException(ResultCode.FAIL);
}
//3.保存
permissionDao.save(perm);
}
/**
* 2.更新权限
*/
public void update(Map<String,Object> map) throws Exception {
Permission perm = BeanMapUtils.mapToBean(map,Permission.class);
//1.通过传递的权限id查询权限
Permission permission = permissionDao.findById(perm.getId()).get();
permission.setName(perm.getName());
permission.setCode(perm.getCode());
permission.setDescription(perm.getDescription());
permission.setEnVisible(perm.getEnVisible());
//2.根据类型构造不同的资源
int type = perm.getType();
switch (type) {
case PermissionConstants.PERMISSION_MENU:
PermissionMenu menu = BeanMapUtils.mapToBean(map,PermissionMenu.class);
menu.setId(perm.getId());
permissionMenuDao.save(menu);
break;
case PermissionConstants.PERMISSION_POINT:
PermissionPoint point =
BeanMapUtils.mapToBean(map,PermissionPoint.class);
point.setId(perm.getId());
permissionPointDao.save(point);
break;
case PermissionConstants.PERMISSION_API:
PermissionApi api = BeanMapUtils.mapToBean(map,PermissionApi.class);
api.setId(perm.getId());
permissionApiDao.save(api);
break;
default:
throw new CommonException(ResultCode.FAIL);
}
//3.保存
permissionDao.save(permission);
}
/**
* 3.根据id查询
* //1.查询权限
* //2.根据权限的类型查询资源
* //3.构造map集合
*/
public Map<String, Object> findById(String id) throws Exception {
Permission perm = permissionDao.findById(id).get();
int type = perm.getType();
Object object = null;
if(type == PermissionConstants.PERMISSION_MENU) {
object = permissionMenuDao.findById(id).get();
}else if (type == PermissionConstants.PERMISSION_POINT) {
object = permissionPointDao.findById(id).get();
}else if (type == PermissionConstants.PERMISSION_API) {
object = permissionApiDao.findById(id).get();
}else {
throw new CommonException(ResultCode.FAIL);
}
Map<String, Object> map = BeanMapUtils.beanToMap(object);
map.put("name",perm.getName());
map.put("type",perm.getType());
map.put("code",perm.getCode());
map.put("description",perm.getDescription());
map.put("pid",perm.getPid());
map.put("enVisible",perm.getEnVisible());
return map;
}
/**
* 4.查询全部
* type : 查询全部权限列表type:0:菜单 + 按钮(权限点) 1:菜单2:按钮(权限点)3:API接

* enVisible : 0:查询所有saas平台的最高权限,1:查询企业的权限
* pid :父id
*/
public List<Permission> findAll(Map<String, Object> map) {
//1.需要查询条件
Specification<Permission> spec = new Specification<Permission>() {
/**
* 动态拼接查询条件
* @return
*/
public Predicate toPredicate(Root<Permission> root, CriteriaQuery<?>
criteriaQuery, CriteriaBuilder criteriaBuilder) {
List<Predicate> list = new ArrayList<>();
//根据父id查询
if(!StringUtils.isEmpty(map.get("pid"))) {
list.add(criteriaBuilder.equal(root.get("pid").as(String.class),
(String)map.get("pid")));
}
//根据enVisible查询
if(!StringUtils.isEmpty(map.get("enVisible"))) {
list.add(criteriaBuilder.equal(root.get("enVisible").as(String.class),
(String)map.get("enVisible")));
}
//根据类型 type
if(!StringUtils.isEmpty(map.get("type"))) {


String ty = (String) map.get("type");
CriteriaBuilder.In<Object> in =
criteriaBuilder.in(root.get("type"));
if("0".equals(ty)) {
in.value(1).value(2);
}else{
in.value(Integer.parseInt(ty));
}
list.add(in);
}
return criteriaBuilder.and(list.toArray(new Predicate[list.size()]));
}
};
return permissionDao.findAll(spec);
}
/**
* 5.根据id删除
* //1.删除权限
* //2.删除权限对应的资源
*
*/
public void deleteById(String id) throws Exception {
//1.通过传递的权限id查询权限
Permission permission = permissionDao.findById(id).get();
permissionDao.delete(permission);
//2.根据类型构造不同的资源
int type = permission.getType();
switch (type) {
case PermissionConstants.PERMISSION_MENU:
permissionMenuDao.deleteById(id);
break;
case PermissionConstants.PERMISSION_POINT:
permissionPointDao.deleteById(id);
break;
case PermissionConstants.PERMISSION_API:
permissionApiDao.deleteById(id);
break;
default:
throw new CommonException(ResultCode.FAIL);
}
}
}

1.2.4 控制器
package com.ihrm.system.controller;
import com.ihrm.common.entity.PageResult;
import com.ihrm.common.entity.Result;
import com.ihrm.common.entity.ResultCode;
import com.ihrm.domain.system.Permission;
import com.ihrm.domain.system.User;
import com.ihrm.system.service.PermissionService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;
//1.解决跨域
@CrossOrigin
//2.声明restContoller
@RestController
//3.设置父路径
@RequestMapping(value="/sys")
public class PermissionController {
@Autowired
private PermissionService permissionService;
/**
* 保存
*/
@RequestMapping(value = "/permission", method = RequestMethod.POST)
public Result save(@RequestBody Map<String,Object> map) throws Exception {
permissionService.save(map);
return new Result(ResultCode.SUCCESS);
}
/**
* 修改
*/
@RequestMapping(value = "/permission/{id}", method = RequestMethod.PUT)
public Result update(@PathVariable(value = "id") String id, @RequestBody
Map<String,Object> map) throws Exception {
//构造id
map.put("id",id);
permissionService.update(map);
return new Result(ResultCode.SUCCESS);
}
/**
* 查询列表
*/
@RequestMapping(value = "/permission", method = RequestMethod.GET)
public Result findAll(@RequestParam Map map) {
List<Permission> list = permissionService.findAll(map);
return new Result(ResultCode.SUCCESS,list);
}
/**
* 根据ID查询
*/
@RequestMapping(value = "/permission/{id}", method = RequestMethod.GET)

public Result findById(@PathVariable(value = "id") String id) throws Exception {
Map map = permissionService.findById(id);
return new Result(ResultCode.SUCCESS,map);
}
/**
* 根据id删除
*/
@RequestMapping(value = "/permission/{id}", method = RequestMethod.DELETE)
public Result delete(@PathVariable(value = "id") String id) throws Exception {
permissionService.deleteById(id);
return new Result(ResultCode.SUCCESS);
}
}

1.3 前端实现


1.3.1 引入权限管理模块


将今日提供的资料module-permissions 引入到工程的/src 文件夹下,在/src/main.js 完成模块注册
import permissions from '@/module-permissions/' // 权限管理
Vue.use(permissions, store)

1.3.2 配置API
在/src/api/base/ 目录下创建permissions.js
import {createAPI} from '@/utils/request'
const api = "/sys/permission"
export const list = data => createAPI(`${api}`, 'get', data)
export const add = data => createAPI(`${api}`, 'post', data)
export const update = data => createAPI(`${api}/${data.id}`, 'put', data)
export const remove = data => createAPI(`${api}/${data.id}`, 'delete', data)
export const detail = data => createAPI(`${api}/${data.id}`, 'get', data)
export const saveOrUpdate = data => {return data.id?update(data):add(data)}

1.3.3 实现权限页面
<template>
<div class="dashboard-container">
<div class="app-container">
<el-card shadow="never">
<el-button class="filter-item fr" size="small" style="margin-left: 10px;"
@click="handleCreate(null,1);setPid(1,'0')" type="primary" icon="el-icon-edit">添加菜单
</el-button>
<el-table :data="dataList" fit style="width: 100%;" highlight-current-row>
<el-table-column fixed prop="name" label="菜单名称" width="200px">
<template slot-scope="scope">
<i :class="scope.row.type==1?'ivu-icon fa fa-folder-open-o fafw':'
ivu-icon el-icon-view'"
:style="scope.row.type==1?'margin-left: 0px':'margin-left:
20px'"></i>
<span @click="show(scope.$index,scope.row.id)">
{{scope.row.name}}</span>
</template>
</el-table-column>
<el-table-column fixed prop="code" label="权限标识" width="200"></eltable-
column>
<el-table-column fixed prop="description" label="描述" width="200"></eltable-
column>
<el-table-column fixed="right" label="操作">
<template slot-scope="scope">
<el-button v-if="scope.row.type==1"
@click="handleCreate(null,2);setPid(2,scope.row.id)" type="text" size="small">添加权限点
</el-button>
<el-button @click="handlerApiList(scope.row.id)" type="text"
size="small">查看api权限</el-button>
<el-button
@click="handleCreate(scope.row.id,scope.row.type);setPid(scope.row.type,scope.row.pid)"
type="text" size="small">查看</el-button>
<el-button @click="handleDelete(scope.row.id)" type="text"
size="small">删除</el-button>
</template>
</el-table-column>
</el-table>
</el-card>
</div>
<el-dialog title="编辑权限" :visible.sync="dialogFormVisible"
style="hight:100px;line-height:1px">
<el-form :model="formData" label-width="90px" style="margin-top:20px">
<el-form-item label="权限名称">
<el-input v-model="formData.name" autocomplete="off" style="width:90%">
</el-input>
</el-form-item>
<el-form-item label="权限标识">
<el-input v-model="formData.code" autocomplete="off" style="width:90%">
</el-input>
</el-form-item>
<el-form-item label="权限描述">
<el-input v-model="formData.description" autocomplete="off"
style="width:90%"></el-input>
</el-form-item>
<div v-if="type==1">
<el-form-item label="菜单顺序">
<el-input v-model="formData.menuOrder" autocomplete="off"
style="width:90%"></el-input>
</el-form-item>
<el-form-item label="菜单icon">
<el-input v-model="formData.menuIcon" autocomplete="off"
style="width:90%"></el-input>
</el-form-item>
</div>
<div v-else-if="type==2">
<el-form-item label="按钮样式">
<el-input v-model="formData.pointClass" autocomplete="off"
style="width:90%"></el-input>
</el-form-item>
<el-form-item label="按钮icon">
<el-input v-model="formData.pointIcon" autocomplete="off"
style="width:90%"></el-input>
</el-form-item>
<el-form-item label="按钮状态">
<el-input v-model="formData.pointStatus" autocomplete="off"
style="width:90%"></el-input>
</el-form-item>
</div>
<div v-else-if="type==3">
<el-form-item label="api请求地址">
<el-input v-model="formData.apiUrl" autocomplete="off"
style="width:90%"></el-input>
</el-form-item>
<el-form-item label="api请求方式">
<el-input v-model="formData.apiMethod" autocomplete="off"
style="width:90%"></el-input>
</el-form-item>
<el-form-item label="api类型">
<el-input v-model="formData.apiLevel" autocomplete="off"
style="width:90%"></el-input>
</el-form-item>
</div>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogFormVisible = false">取 消</el-button>
<el-button type="primary" @click="saveOrUpdate">确 定</el-button>
</div>
</el-dialog>
<el-dialog title="API权限列表" :visible.sync="apiDialogVisible"
style="hight:400px;line-height:1px">
<el-button class="filter-item fr" size="small" style="margin-left: 10px;"
@click="handleCreate(null,1);setPid(3,pid)" type="primary" icon="el-icon-edit">添加api权
限</el-button>
<el-table :data="apiList" fit style="width: 100%;" max-height="250" >
<el-table-column fixed prop="name" label="菜单名称" width="120px"></eltable-
column>
<el-table-column fixed prop="code" label="权限标识" width="200"></eltable-
column>
<el-table-column fixed prop="description" label="描述" width="200"></eltable-
column>
北京市昌平区建材城西路金燕龙办公楼一层 电话:400-618-9090
<el-table-column fixed="right" label="操作" width="200">
<template slot-scope="scope">
<el-button
@click="handleCreate(scope.row.id,scope.row.type);setPid(scope.row.type,scope.row.pid)"
type="text" size="small">查看</el-button>
<el-button
@click="handleDelete(scope.row.id);handlerApiList(pid)" type="text" size="small">删除
</el-button>
</template>
</el-table-column>
</el-table>
</el-dialog>
</div>
</template>
<script>
import {saveOrUpdate,list,detail,remove} from "@/api/base/permissions"
export default {
name: 'permissions-table-index',
data() {
return {
MenuList: 'menuList',
type:0,
pid:"",
dialogFormVisible:false,
apiDialogVisible:false,
formData:{},
dataList:[],
apiList:[],
pointEnable:{}
}
},
methods: {
setPid(type,pid){
this.pid = pid;
this.type = type
},
handleCreate(id) {
if(id && id !=undefined) {
detail({id}).then(res => {
this.formData = res.data.data
this.dialogFormVisible=true
})
}else{
this.formData = {}
this.dialogFormVisible=true
}
},
saveOrUpdate() {
this.formData.type = this.type
this.formData.pid = this.pid
saveOrUpdate(this.formData).then(res => {
this.$message({message:res.data.message,type:res.data.success?"success":"error"});
if(res.data.success){
this.formData={};
this.dialogFormVisible=false;
}
if(this.type ==3){
this.handlerApiList(this.pid);
}else{
this.getList();
this.pointEnable = {}
}
})
},
handleDelete(id) {
remove({id}).then(res=> {
this.$message({message:res.data.message,type:res.data.success?"success":"error"});
})
},
getList() {
list({type:1,pid:0}).then(res=> {
this.dataList = res.data.data
})
},
show(index,id) {
if(!this.pointEnable[id] == null || this.pointEnable[id]==undefined){
list({type:2,pid:id}).then(res=> {
for(var i = 0 ; i <res.data.data.length;i++) {
this.dataList.splice(index+1,0,res.data.data[i]);
}
this.pointEnable[id] = res.data.data.length;
console.log(this.dataList)
})
}else{
this.dataList.splice(index+1,this.pointEnable[id])
this.pointEnable[id] = null;
}
},
handlerApiList(id) {
this.pid = id;
list({type:3,pid:id}).then(res=> {
this.apiList = res.data.data
this.apiDialogVisible = true;
})
}
},
created () {
this.getList();
}
}

 


2 分配角色


2.1 需求分析


由于使用了RBAC模型对权限进行统一管理,所以每个SAAS-HRM平台的用户都应该具有角色的信息。进而通过角
色完成对权限的识别。众所周知,一个用户可以具有很多的角色,一个角色可以被分配给不同的用户。所以用户和
角色之间是多对多关。

 

博学谷-基于SaaS平台的iHRM实战开发05-权限分配与jwt概述第五天

2.2 服务端代码实现


(1) 改造用户实体类,添加角色的id集合属性,表明一个用户具有的多个角色id
在com.ihrm.system.domain.User 用户实体类中添加与角色的多对多关系并进行JPA的配置
@ManyToMany
@JsonIgnore
@JoinTable(name="pe_user_role",joinColumns=
{@JoinColumn(name="user_id",referencedColumnName="id")},
inverseJoinColumns={@JoinColumn(name="role_id",referencedColumnName="id")}
)
private Set<Role> roles = new HashSet<Role>();//用户与角色 多对多

在com.ihrm.system.domain.Role角色实体类中配置角色与用户的多对多关系并进行JPA配置
@JsonIgnore
@ManyToMany(mappedBy="roles")
private Set<User> users = new HashSet<User>(0);//角色与用户 多对多
(2) 在com.ihrm.system.controller.UserController 添加分配角色的控制器方法实现

/**
* 分配角色
*/
@RequestMapping(value = "/user/assignRoles", method = RequestMethod.PUT)
public Result assignRoles(@RequestBody Map<String,Object> map) {
//1.获取被分配的用户id
String userId = (String) map.get("id");
//2.获取到角色的id列表
List<String> roleIds = (List<String>) map.get("roleIds");
//3.调用service完成角色分配
userService.assignRoles(userId,roleIds);
return new Result(ResultCode.SUCCESS);
}

(3) 业务逻辑层添加分配角色的业务方法
/**
* 分配角色
*/
public void assignRoles(String userId,List<String> roleIds) {
//1.根据id查询用户
User user = userDao.findById(userId).get();
//2.设置用户的角色集合
Set<Role> roles = new HashSet<>();
for (String roleId : roleIds) {
Role role = roleDao.findById(roleId).get();
roles.add(role);
}
//设置用户和角色集合的关系
user.setRoles(roles);
//3.更新用户
userDao.save(user);
}

2.3 前端代码实现


(1) \src\module-employees 添加分配角色的组件
<template>
<div class="add-form">
<el-dialog title="分配角色" :visible.sync="roleFormVisible" style="height:300px">
<el-form :model="formBase" label-position="left" label-width="120px"
style='margin-left:120px; width:500px;'>
<el-checkbox-group
v-model="checkedCities1">
<el-checkbox v-for="(item,index) in cities" :label="item.id" :key="index">
{{item.name}}</el-checkbox>
</el-checkbox-group>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="createData">提交</el-button>

<el-button @click="roleFormVisible=false">取消</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import {findAll} from "@/api/base/role"
import {assignRoles} from "@/api/base/users"
export default {
data () {
return {
roleFormVisible:false,
formBase:{},
checkedCities1:[],
data:[],
cities:[],
id:null
}
},
methods: {
toAssignPrem(id) {
findAll().then(res => {
this.id = id;
this.cities = res.data.data
this.roleFormVisible=true
})
},
createData() {
assignRoles({id:this.id,ids:this.checkedCities1}).then(res => {
this.$message({message:res.data.message,type:res.data.success?"success":"error"});
this.roleFormVisible=false
})
}
}
}
</script>

(2) \src\module-employees\pages\employees-list.vue 引入组件
<!--分配角色组件 -->
<component v-bind:is="addRole" ref="addRole"></component>

 

3 分配权限


3.1 需求分析


完成对角色权限的分配。

博学谷-基于SaaS平台的iHRM实战开发05-权限分配与jwt概述第五天

3.2 服务端代码实现


(1) 角色实体类中添加与权限的多对多关系并进行JPA配置
@JsonIgnore //忽略json转化
@ManyToMany
@JoinTable(name="pe_role_permission",
joinColumns={@JoinColumn(name="role_id",referencedColumnName="id")},
inverseJoinColumns=
{@JoinColumn(name="permission_id",referencedColumnName="id")})
private Set<Permission> permissions = new HashSet<Permission>(0);//角色与模块 多对多

(2)控制器类( com.ihrm.system.controller.RoleController )添加权限分配
/**
* 分配权限
*/
@RequestMapping(value = "/role/assignPrem", method = RequestMethod.PUT)
public Result assignPrem(@RequestBody Map<String,Object> map) {
//1.获取被分配的角色的id
String roleId = (String) map.get("id");
//2.获取到权限的id列表
List<String> permIds = (List<String>) map.get("permIds");
//3.调用service完成权限分配
roleService.assignPerms(roleId,permIds);
return new Result(ResultCode.SUCCESS);
}

(3) 持久化类中添加分配权限方法
/**
* 分配权限
*/
public void assignPerms(String roleId,List<String> permIds) {
//1.获取分配的角色对象
Role role = roleDao.findById(roleId).get();
//2.构造角色的权限集合
Set<Permission> perms = new HashSet<>();
for (String permId : permIds) {
Permission permission = permissionDao.findById(permId).get();
//需要根据父id和类型查询API权限列表
List<Permission> apiList =
permissionDao.findByTypeAndPid(PermissionConstants.PERMISSION_API, permission.getId());
perms.addAll(apiList);//自定赋予API权限
perms.add(permission);//当前菜单或按钮的权限
}
System.out.println(perms.size());
//3.设置角色和权限的关系
role.setPermissions(perms);
//4.更新角色
roleDao.save(role);
}

3.3 前端代码实现


(1)在\src\module-settings\components\role-list.vue 绑定权限按钮
<el-table-column fixed="right" label="操作" align="center" width="250">
<template slot-scope="scope">
<el-button @click="handlerPerm(scope.row)" type="text" size="small">分配权限</elbutton>
<el-button @click="handleUpdate(scope.row)" type="text" size="small">修改</elbutton>
<el-button @click="handleDelete(scope.row)" type="text" size="small">删除</elbutton>
</template>
</el-table-column>

(2)在\\src\api\base\role.js 中添加分配权限的API方法
export const assignPrem = data => createAPI(`/sys/role/assignPrem`, 'put', data)

(3) \src\module-settings\components\role-list.vue 使用Element-UI构造权限树
<el-dialog :title="'为【'+formData.name+'】分配权限'" :visible.sync="permFormVisible"
style="hight:100px;line-height:1px">
<el-tree
:data="treeData"
default-expand-all
show-checkbox
node-key="id"
ref="tree"
:default-checked-keys="checkNodes"

:props="{label:'name'}">
</el-tree>
<div slot="footer" class="dialog-footer">
<el-button @click="permFormVisible = false">取 消</el-button>
<el-button type="primary" @click="assignPrem">确 定</el-button>
</div>
</el-dialog>


(4) 完成添加权限
import {list,add,update,remove,detail,assignPrem} from "@/api/base/role"
import * as permApi from "@/api/base/permissions"
import commonApi from "@/utils/common"
import PageTool from './../../components/page/page-tool'
var _this = null
export default {
name: 'roleList',
components: {PageTool},
props: ['objId'],
data() {
return {
formData:{},
treeData:[],
checkNodes:[],
dialogFormVisible: false,
permFormVisible:false,
dataList:[],
counts:0,
requestParameters:{
page: 1,
pagesize: 10
}
}
},
methods: {
assignPrem() {
assignPrem({roleId:this.formData.id,ids:this.$refs.tree.getCheckedKeys()}).then(res =>
{
this.$message({message:res.data.message,type:res.data.success?"success":"error"});
this.permFormVisible=false
})
},
handlerPerm(obj) {
detail({id:obj.id}).then(res=>{
this.formData = res.data.data;
if(this.formData.menusIds != null) {
this.checkNodes = this.formData.menusIds.split(",")
}
if(this.formData.pointIds != null) {
this.checkNodes.push(this.formData.pointIds.split(","))
}
permApi.list({type:0,pid:null}).then(res => {
this.treeData = commonApi.transformTozTreeFormat(res.data.data)
this.permFormVisible=true
})
})
},
handlerAdd() {
this.formData={}
this.dialogFormVisible = true
},
handleDelete(obj) {
this.$confirm(
`本次操作将删除${obj.name},删除后角色将不可恢复,您确认删除吗?`
).then(() => {
remove({id: obj.id}).then(res => {
this.$message({message:res.data.message,type:res.data.success?"success":"error"});
this.doQuery()
})
})
},
handleUpdate(obj) {
detail({id:obj.id}).then(res=>{
this.formData = res.data.data;
this.formData.id = obj.id;
this.dialogFormVisible = true
})
},
saveOrUpdate() {
if(this.formData.id == null || this.formData.id == undefined) {
this.save()
}else{
this.update();
}
},
update(){
update(this.formData).then(res=>{
this.$message({message:res.data.message,type:res.data.success?"success":"error"});
if(res.data.success){
this.formData={};
this.dialogFormVisible=false;
this.doQuery();
}
})
},
save() {
add(this.formData).then(res=>{
this.$message({message:res.data.message,type:res.data.success?"success":"error"});
if(res.data.success){
this.formData={};
this.dialogFormVisible=false;
this.doQuery();
}
})
},
// 获取详情
doQuery() {
list(this.requestParameters).then(res => {
this.dataList = res.data.data.rows
this.counts = res.data.data.total
})
},
// 每页显示信息条数
handleSizeChange(pageSize) {
this.requestParameters.pagesize = pageSize
if (this.requestParameters.page === 1) {
_this.doQuery(this.requestParameters)
}
},
// 进入某一页
handleCurrentChange(val) {
this.requestParameters.page = val
_this.doQuery()
},
},
// 挂载结束
mounted: function() {},
// 创建完毕状态
created: function() {
_this = this
this.doQuery()
},
// 组件更新
updated: function() {}
}
</script>

第4章未完!!!!请看第六天学习内容!!!

博学谷-基于SaaS平台的iHRM实战开发05-权限分配与jwt概述第五天

博学谷-基于SaaS平台的iHRM实战开发05-权限分配与jwt概述第五天

博学谷-基于SaaS平台的iHRM实战开发05-权限分配与jwt概述第五天

https://www.boxuegu.com/promote/detail-1232.html

基于SaaS平台的iHRM实战开发

百度网盘下载链接:
链接: https://pan.baidu.com/s/1repa2B4XYycXNK4pO8QyAw  密码: vl27

如果失效联系v信:itit11223344