Skip to content
🎨 作者:路斐 📔 阅读量:

平台权限管理前端设计

用户登录流程

用户认证

平台使用 JWT(JSON Web Token) 进行用户认证,客户端通过登录接口获取 JWT 并保存,在访问接口数据时,需要携带 JWT,将 JWT 放在请求的 Authorization 头部。例如:

登录

import axios from 'axios';
var url = 'http://10.7.55.191:8000/api/token/';
var formData = new FormData();
formData.append('username', 'admin');
formData.append('password', '123456');
axios.post(url, formData).then(res=>{
    setStorage("token", res.data.data.access);
    setStorage("refresh", res.data.data.refresh);
})

访问数据

import axios from "axios";
var url = 'http://10.7.55.191:8000/api/version/';
var token = getStorage("token");
var headers = {
        Authorization: "JWT " + token,
      },
axios.get(url, {headers: headers})

上面用到的两个函数 setStoragegetStorage, 分别是保存和读取存储中的数据,具体会根据前端环境去实现。例如当前我们将用户数据保存在浏览器的 localStorage 中:

export function setStorage(key, value) { window.localStorage.setItem(key, JSON.stringify(value)) }

export function getStorage(key) { return JSON.parse(window.localStorage.getItem(key)) }

JWT 的详细设计可以参考 官方文档

当 access token 过期时,客户端可以通过 refresh token 刷新 access token。

http://10.7.55.191:8000/api/ 使我们的开发 API 地址

用户资源

登录后,客户端会开始获取用户资源,包括:

  1. 菜单列表及菜单中的按钮权限
  2. 用户角色、用户部门

研测平台的策略是仅显示用户有权限访问的菜单和对应的按钮。

研测平台的权限设计

研测平台前端的权限主体是角色,例如【管理员】、【测试】,客体是菜单和按钮,例如【新建】、【删除】。

对应的后端权限的客体是 接口 + 方法,前端的每个按钮与之对应。这种对应关系由管理员用户维护,即【系统管理】->【菜单管理】中的【按钮配置】功能。

一般来说前端菜单对应后端不同的接口,按钮对应接口的不同操作(GET,PUT,POST,PATCH,DELETE),但研测平台的不同的菜单可能对应后端同一个接口,不同的按钮也可能对应不同的接口。例如:

  • 【版本测试】和【系统测试】其实是同一个后端接口实现的,但是有不同的前端菜单;
  • 同一个任务页面【启动】按钮和【新建】按钮对应的不同的后端接口。

因此前端的权限还需要按照菜单区分,例如菜单A和菜单B都使用接口A,但是角色A和角色B需要对菜单A和菜单B有不同的权限,可以看到【按钮配置】是在对不同的菜单进行配置的。

研测平台前端通过权限确认是否显示某个菜单或按钮。例如下面是控制按钮显示的函数:

function isShowBtn(url, moduleName, btnName) {
  /* 
    url: 前端路由
    moduleName: 菜单名称
    btnName: 按钮,即 http://10.7.13.132:8081/#/buttonManage 下的按钮的 Key
  */
  if (getStorage("is_superuser") == "true") {
    return true;
  }
  let btnArr = getStorage("menuList") ? JSON.parse(getStorage("menuList")) : [];
  let isshow = false;
  for (var i = 0; i < btnArr.length; i++) {
    let item = btnArr[i];
    if (
      item.url == url &&
      item.moduleName == moduleName &&
      item.menuPermission &&
      item.menuPermission.includes(btnName)
    ) {
      isshow = true;
      break;
    }
  }
  return isshow;
}

权限主体和客体的关联即【权限配置】由管理员在【系统管理】-> 【权限管理】中维护。

研测平台的伪权限

伪权限是前端自己实现的权限,例如:用户作为权限主体(即每个用户有专属的权限)。

在机器的占用和释放中,需要对单个用户做权限控制。这里则由机器的用户名属性来控制,平台会判断当前用户是否该机器的占用用户来实现伪权限。下面是一个控制伪权限的函数:

export function hasPerm(pm) {
    return getStorage("userId") === pm.user || getStorage("is_superuser") == 'true'
}

getStorage 是获取存储数据的函数。我们在登录的时候,通过 setStorageuiserId 保存在浏览器中。