前端权限管理

matevip 2021-6-15 大约 4 分钟

# 一、权限管理

权限控制是中后台系统中常见的需求之一,你可以利用我们提供的 路由权限指令权限,实现一些基本的权限控制功能,脚手架中也包含了几个简单示例以提供参考。

# 1.1 路由和默认权限控制

Plus 提供了两套权限实现方案,其中默认方案为前端固定路由表和权限配置,由后端提供用户权限标识,来识别是否拥有该路由权限。另一套方案为后端提供权限和路由信息结构接口,动态生成权限和菜单。

默认实现方式是通过获取当前用户的权限去比对路由表,生成当前用户具有的权限可访问的路由表,通过 router.addRoutes 动态挂载到 router 上。

整体流程可以看这张图:

# 步骤如下:

  1. 判断是否有 AccessToken 如果没有则跳转到登录页面
  2. 获取用户信息和拥有权限store.dispatch('GetInfo')
  3. 用户信息获取成功后, 调用 store.dispatch('GenerateRoutes', userInfo) 根据获取到的用户信息构建出一个已经过滤好权限的路由结构(src/store/modules/permission.js)
  4. 将构建的路由结构信息利用 Vue-Router 提供的动态增加路由方法 router.addRoutes 加入到路由表中
  5. 加入路由表后将页面跳转到用户原始要访问的页面,如果没有 redirect 则进入默认页面 (/dashboard/workplace)

这里可以看出把 登录 和 获取用户信息 分成了两个接口,主要目的在于当用户刷新页面时,可以根据登录时获取到的身份令牌(cookie/token)等,去获取用户信息,从而避免刷新需要调用登录接口

Plus 实现的路由权限的控制代码都在 @/permission.js 中,如果想修改逻辑,直接在适当的判断逻辑中 next() 释放钩子即可。 两套权限实现 均使用 @/permission.js (路由守卫)来进行控制。

# 1.2 主要流程

  • permission.js 中,添加了全局路由守卫,路由切换时验证登录状态,即本地是否有token
  • 如果本地没有存储 token 则跳转至登陆界面,登录成功后将 token 存储在本地,后续请求携带 token 凭证进行鉴权;
  • 在路由跳转时,新的路由渲染之前,调用方法凭 token 获取用户信息,存储在Vuex中。
  • 若用户信息获取失败(通常是因为token过期导致鉴权失败),会导致系统跳转至登陆界面,重新登录以获得有效的token。
  • 若用户信息获取成功,则进入系统。

# 1.3 权限管理

通过Getinfo方法,发起请求获取这个账号的权限信息

路径地址: src/store/modules/user.js

// 获取用户信息
GetInfo({ commit }) {
  return new Promise((resolve, reject) => {
    getLoginUser()
      .then(response => {
        if (response.code === 200) {
          const data = response.data;
          commit('SET_ADMINTYPE', data.adminType);
          commit('SET_ROLES', 1);
          commit('SET_BUTTONS', data.permissions);
          commit('SET_INFO', data);
          commit('SET_NAME', { name: data.name, welcome: welcome() });
          commit('SET_TENANTID', data.tenantId === '' ? '1' : data.tenantId);
          Vue.ls.set(TENANT_ID, data.tenantId === '' ? '1' : data.tenantId);
          if (data.avatar != null) {
            commit('SET_AVATAR', data.avatar);
          }
          resolve(data);
        } else {
          // eslint-disable-next-line no-undef
          reject(new Error(data.message));
        }
      })
      .catch(error => {
        reject(error);
      });
  });
},
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

之后我们将map返回的权限相关信息存储到vuex中,这样我们就能全局获取到这个用户的权限了 同时将登录用户的账号权限信息return回permission.js中继续下一步操作

我们获取用户权限信息的目的就是拿用户权限与路由表进行匹配,筛选出与之相符合的路由,我们把视线转移到permission.js中,当获取到用户的权限信息后,下一步操作就是要去匹配路由表了,代码如下:

store.dispatch('GenerateRoutes', { antDesignmenus }).then(() => {
  // 动态添加可访问路由表
  router.addRoutes(store.getters.addRouters);
  // 请求带有 redirect 重定向时,登录自动重定向到该地址
  const redirect = decodeURIComponent(from.query.redirect || to.path);
  if (to.path === redirect) {
    next({ path: redirect });
    // hack方法 确保addRoutes已完成 ,set the replace: true so the navigation will not leave a history record
    next({ ...to, replace: true });
  } else {
    // 跳转到目的路由
    next({ path: redirect });
  }
});
})
.catch(() => {
store.dispatch('Logout').then(() => {
  next({ path: '/user/login', query: { redirect: to.fullPath } });
});
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

在GetInfo的回调函数内,调用了GenerateRoutes方法,我们需要做的就是将在GetInfo中获取到的用户账号信息以参数的方式传递到GenerateRoutes中

路径地址: src/store/modules/permission.js

上次编辑于: 2021年6月15日 23:19
贡献者: matevip , 秦旭洋