从0到1搭建element后台框架之权限篇

栏目: JavaScript · 发布时间: 5年前

内容简介:首先还是谢谢各位童鞋的大大的赞赞,你们的支持是我前进的动力!上周写了一篇现在大多数项目都是采用jwt授权认证,也就是我们所熟悉的token登录身份校验机制,jwt的好处多多,由于jwt是由服务端生成,中间人修改密串后,服务端会校验不过,安全有效。一般呆在请求头上的首先在路由跳转的时候需要验证

前言

首先还是谢谢各位童鞋的大大的赞赞,你们的支持是我前进的动力!上周写了一篇 从0到1搭建element后台框架 ,很多童鞋留言提到权限问题,这一周就给大家补上。 GitHub

一、jwt授权认证

现在大多数项目都是采用jwt授权认证,也就是我们所熟悉的token登录身份校验机制,jwt的好处多多,由于jwt是由服务端生成,中间人修改密串后,服务端会校验不过,安全有效。一般呆在请求头上的 Authorization 里面。前端童鞋一般获取token后通过vuex存储起来,随后数据持久化存到session中。

路由跳转验证token

首先在路由跳转的时候需要验证 vuex 是否存储了token,如果没有token的话直接跳到登陆页面获取token。

if (to.path !== '/login' && !store.state.token) {
        next('/login')
        NProgress.done() // 结束Progress
      } else {
        next();
     }

请求拦截带上token

详细请看项目中的 router.js
本地存在token之后,我们在每次请求接口的时候都需要带上token来验证token的合法性。

//在请求前拦截
    if (store.state.token) {
            config.headers["Authorization"] = "Bearer " + store.state.token;
        }

如果token不合法,全局错误处理,直接跳到登陆页面

case 401:
        messages("warning", "用户登陆过期,请重新登陆");
        store.commit('COMMIT_TOKEN','')
        setTimeout(() => {
            router.replace({
                path: "/login",
                query: {
                    redirect: router.currentRoute.fullPath
                }
            });
        }, 1000);
        break;

详细代码看项目中的 request.js

二、菜单权限

本项目中,我主要是通过后端传过来的角色类型来判断导航菜单的显示与隐藏。

也就是说首先前端请求接口,后端返回token,以及对应的角色,比如项目中用 admin 登陆的话, roles=['admin'] ,用 user 登陆的话 roles=['user']

接下来我这边设计了一份菜单表和一份路由表,路由表主要是为了注册路由,不需要考虑层级关系。而菜单表需要考虑层级关系,里面可以配置主菜单,子菜单,图标等等一系列的东西,当然菜单表最好是通过接口数据从后端传过来。值得注意的是无论是菜单表,还是路由表,里面都有一个 meta 配置项。里面可以配置我们的角色权限。路由表对应的菜单表角色权限需要一致。没有配置角色权限的菜单默认都开放。

menu.js

{
        icon: "el-icon-question",
        index: "premission",
        title: "权限测试",
        subs: [{
            index: "permission",
            title: "菜单测试",
            meta: {
                roles: ['admin']
            }
        },
        {
            index: "permissionBtn",
            title: "按钮权限",
        },
    
        ]
    }

router.js

{
      path: '/permission',
      component: getComponent('permission', 'permission'),
      meta: {
        title: '菜单权限',
        roles: ['admin']
      }
    },

根据角色过滤菜单

现在我们开始编写菜单逻辑,进入 Aside.vue ,首先根据角色过滤菜单表 menu.js

/**
     * @param {Arrary} menus 菜单
     * @param {Arrary} roles 角色
     * @return {Arrary} res 过滤后的菜单
     */
    filterMenus(menus, roles) {
      const res = [];
      menus.forEach(route => {
        const tmp = { ...route };
        //hasPermission判断权限是否匹配
        if (this.hasPermission(roles, tmp)) {
          if (tmp.subs) {
            tmp.subs = this.filterMenus(tmp.subs, roles);
          }
          res.push(tmp);
        }
      });
      return res;
    },
/**
     * 通过meta.role判断是否与当前用户权限匹配
     * @param roles
     * @param menu
     */
    hasPermission(roles, menu) {
      if (menu.meta && menu.meta.roles) {
        return roles.some(role => menu.meta.roles.includes(role));
      } else {
        return true;
      }
    },

过滤结果

computed: {
        items() {
          let items = this.filterMenus(menu, this.$store.state.roles);
          return items;
        }
      },

这样就获得了权限菜单

到目前为止,权限控制基本完成,不过在项目运行的过程中,还发现一个bug。本项目中存在一个 tagList ,也就是打开的导航标签,当用户从 admin 切换到 user 的时候打开的导航标签依旧存在,也就是说用户可以通过导航标签进入premission页面。此时我这边直接通过路由拦截来处理此时的情况。

if(to.meta.roles){
        to.meta.roles.includes(...store.getters.roles)?next():next('/404')
      }else{
        next();
     }

没有权限的页面一律进入404页面。

三、按钮权限控制

按钮级别的权限说实话一般都通过数据接口来控制是否展示,点击等等情况。如果光有前端来控制绝对不是可行之道。

项目中按钮权限注册全局自定义指令来完成的。首先 src 下面新建一个 directive 文件夹,用于注册全局指令。在文件夹下新建一个 premissionBtn.js 。如果对自定义指令不熟的话可以查阅 官方文档

全局指令

import Vue from 'vue'
    import store from '@/store/store'
    //注册一个v-allowed指令
     Vue.directive('allowed', {
        inserted: function (el, bingding) {
            let roles = store.getters.roles
            //判断权限
            if (Array.isArray(roles) && roles.length > 0) {
                let allow = bingding.value.some(item => {
                    return roles.includes(item)
                })
                if (!allow) {
                    if (el.parentNode) {
                        el.parentNode.removeChild(el)
                    }
                }
            }
        }
    })

引用

import './directive/premissionBtn'

那自定义指令如何使用呢?

<div class="premissionBtn">
        <el-button type="primary" v-allowed="['admin']">我是只有admin的时候才能显示</el-button>
        <br>
        <el-button type="info" v-allowed="['user']">我是只有user的时候才能显示</el-button>
        <br>
        <el-button type="warning" v-allowed="['admin','user']">我是admin或者user才能显示</el-button>
        <br>
        <el-button type="danger">任何角色都可以显示</el-button>
    </div>

后记

本项目还有许多需要完善和优化的地方,最后项目存在着不足或者更好的方法,请及时提出来,方便修正。谢谢大家。


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

An Introduction to Genetic Algorithms

An Introduction to Genetic Algorithms

Melanie Mitchell / MIT Press / 1998-2-6 / USD 45.00

Genetic algorithms have been used in science and engineering as adaptive algorithms for solving practical problems and as computational models of natural evolutionary systems. This brief, accessible i......一起来看看 《An Introduction to Genetic Algorithms》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试