從0到1搭建element後臺框架之權限篇

前言

首先仍是謝謝各位童鞋的大大的贊贊,大家的支持是我前進的動力!上週寫了一篇從0到1搭建element後臺框架,不少童鞋留言提到權限問題,這一週就給你們補上。GitHubjavascript

1、jwt受權認證

如今大多數項目都是採用jwt受權認證,也就是咱們所熟悉的token登陸身份校驗機制,jwt的好處多多,因爲jwt是由服務端生成,中間人修改密串後,服務端會校驗不過,安全有效。通常呆在請求頭上的Authorization裏面。前端童鞋通常獲取token後經過vuex存儲起來,隨後數據持久化存到session中。
html

路由跳轉驗證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的合法性。vue

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

若是token不合法,全局錯誤處理,直接跳到登錄頁面java

case 401:
        messages("warning", "用戶登錄過時,請從新登錄");
        store.commit('COMMIT_TOKEN','')
        setTimeout(() => {
            router.replace({
                path: "/login",
                query: {
                    redirect: router.currentRoute.fullPath
                }
            });
        }, 1000);
        break;

詳細代碼看項目中的request.jsgit

2、菜單權限

本項目中,我主要是經過後端傳過來的角色類型來判斷導航菜單的顯示與隱藏。
也就是說首先前端請求接口,後端返回token,以及對應的角色,好比項目中用admin登錄的話,roles=['admin'],用user登錄的話roles=['user']

接下來我這邊設計了一份菜單表和一份路由表,路由表主要是爲了註冊路由,不須要考慮層級關係。而菜單表須要考慮層級關係,裏面能夠配置主菜單,子菜單,圖標等等一系列的東西,固然菜單表最好是經過接口數據從後端傳過來。值得注意的是不管是菜單表,仍是路由表,裏面都有一個meta配置項。裏面能夠配置咱們的角色權限。路由表對應的菜單表角色權限須要一致。沒有配置角色權限的菜單默認都開放。
github

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.jsvuex

/**
     * @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頁面。此時我這邊直接經過路由攔截來處理此時的狀況。segmentfault

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

沒有權限的頁面一概進入404頁面。後端

3、按鈕權限控制

按鈕級別的權限說實話通常都經過數據接口來控制是否展現,點擊等等狀況。若是光有前端來控制絕對不是可行之道。

項目中按鈕權限註冊全局自定義指令來完成的。首先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>

後記

本項目還有許多須要完善和優化的地方,最後項目存在着不足或者更好的方法,請及時提出來,方便修正。謝謝你們。

相關文章連接

從0到1搭建element後臺框架

(打包優化)從0到1搭建element後臺框架優化篇

相關文章
相關標籤/搜索