# 权限管理的小秘密

​ 在 Web 系统中,页面的权限分为三个维度(路由的访问、按钮的展示、接口的请求),如何根据角色规范其能做得事情尤为重要。

# 准备工作

  • 通过 Vue-Cli 初始化项目

    目录结构

  • PageHome.vue

    <template>
      <div id="PageHome">
        <h1>我是首页 不管是谁都能正常访问</h1>
        <ul>
          <li>
            <router-link to="login">登录按钮 未登录的用户才看得到</router-link>
          </li>
          <li>
            <router-link to="Controller">权限按钮 超级管理员才看得到</router-link>
          </li>
          <li>
            <router-link to="List">列表按钮 已登录的用户才看得到</router-link>
          </li>
        </ul>
      </div>
    </template>
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
  • router.js

    import Vue from 'vue';
    import VueRouter from 'vue-router';
    
    Vue.use(VueRouter);
    
    const routes = [
      {
        path: '/',
        name: 'home',
        component: () => import('../views/PageHome.vue'),
        meta: {
          routerName: '首页',
        },
      },
      {
        path: '/login',
        name: 'login',
        component: () => import('../views/PageLogin.vue'),
        meta: {
          routerName: '登录页',
        },
      },
      {
        path: '/controller',
        name: 'controller',
        component: () => import('../views/PageController.vue'),
        meta: {
          routerName: '权限页',
        },
      },
      {
        path: '/list',
        name: 'list',
        component: () => import('../views/PageList.vue'),
        meta: {
          routerName: '列表页',
        },
      },
    ];
    
    const router = new VueRouter({
      routes,
    });
    
    export default router;
    
    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
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45

# 区分角色

​ 在本次案例中,我们将分为三个不同角色(未登录用户、普通用户、超管)。

角色 页面权限
未登录用户 首页、登录页
普通用户 首页、列表页
超级管理员 首页、列表页、权限页
  • 通过 登录页 模拟用户登录

    <template>
      <div id="pageLogin">
        <button @click="userLogin('admin')">admin登录</button>
        <button @click="userLogin('user')">普通用户登录</button>
      </div>
    </template>
    
    <script>
    export default {
      methods: {
        userLogin(role) {
          this.$store.commit('changeUserRole', role);
          this.$router.push('/');
        },
      },
    };
    </script>
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
  • 用户信息储存 VueX

    import Vue from 'vue';
    import Vuex from 'vuex';
    
    Vue.use(Vuex);
    
    export default new Vuex.Store({
      state: {
        userRole: sessionStorage.getItem('role') || '',
      },
      mutations: {
        /**
         * 更新当前用户权限
         * @param {*} state 仓库
         * @param {*} roleName 角色名称
         */
        changeUserRole(state, roleName) {
          sessionStorage.setItem('role', roleName);
          state.userRole = roleName;
        },
      }
    });
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
  • 现在我们就可以模拟三种角色(未登录用户、普通用户、超管)

# 页面权限

​ 观察上面的 router.js 发现不管是什么角色可以访问所有页面,所以我们要针对不同的角色开始设定对应的 页面权限

# 简单版页面权限

​ 因为现在后台只返回角色的名字,没有返回角色的具体权限,这时候的页面权限完全交给前端来判断,所以,我们都会通过 路由前置守卫 来判断。

// 未登录用户权限
const noLoginRole = ['home', 'login'];

// 普通用户权限
const userRole = ['home', 'list'];

// 路由前置守卫
router.beforeEach((to, from, next) => {
  if (sessionStorage.getItem('role') == '') {
    if (noLoginRole.includes(to.name)) {
      next();
    } else {
      next('/');
    }
  } else if (sessionStorage.getItem('role') == 'user') {
    if (userRole.includes(to.name)) {
      next();
    } else {
      next('/');
    }
  } else {
    next();
  }
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

​ 我们通过角色来设置对应的权限 noLoginRoleuserRole 但是 会发现这种设置方法不利于后期维护。

# 升级版页面权限

​ 通过页面配置角色权限,将对应权限保存到后台,登录时返回对应角色和具体路由权限。