• <fieldset id="8imwq"><menu id="8imwq"></menu></fieldset>
  • <bdo id="8imwq"><input id="8imwq"></input></bdo>
    最新文章專題視頻專題問答1問答10問答100問答1000問答2000關鍵字專題1關鍵字專題50關鍵字專題500關鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關鍵字專題關鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
    問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
    當前位置: 首頁 - 科技 - 知識百科 - 正文

    基于Vue實現后臺系統權限控制的示例代碼

    來源:懂視網 責編:小采 時間:2020-11-27 22:31:24
    文檔

    基于Vue實現后臺系統權限控制的示例代碼

    基于Vue實現后臺系統權限控制的示例代碼:用Vue/React這類雙向綁定框架做后臺系統再適合不過,后臺系統相比普通前端項目除了數據交互更頻繁以外,還有一個特別的需求就是對用戶的權限控制,那么如何在一個Vue應用中實現權限控制呢?下面是我的一點經驗。 權限控制是什么 在權限的世界里服務端提供的一
    推薦度:
    導讀基于Vue實現后臺系統權限控制的示例代碼:用Vue/React這類雙向綁定框架做后臺系統再適合不過,后臺系統相比普通前端項目除了數據交互更頻繁以外,還有一個特別的需求就是對用戶的權限控制,那么如何在一個Vue應用中實現權限控制呢?下面是我的一點經驗。 權限控制是什么 在權限的世界里服務端提供的一

    用Vue/React這類雙向綁定框架做后臺系統再適合不過,后臺系統相比普通前端項目除了數據交互更頻繁以外,還有一個特別的需求就是對用戶的權限控制,那么如何在一個Vue應用中實現權限控制呢?下面是我的一點經驗。

    權限控制是什么

    在權限的世界里服務端提供的一切都是資源,資源可以由請求方法+請求地址來描述,權限是對特定資源的訪問許可,所謂權限控制,也就是確保用戶只能訪問到被分配的資源。具體的說,前端對資源的訪問通常是由界面上的按鈕發起,比如刪除某條數據;或由用戶進入某一個頁面發起,比如獲取某個列表數據。這兩種形式覆蓋了資源請求的大部分場景,因此權限控制也可以被籠統的分成菜單權限控制和按鈕權限控制。

    Vue菜單權限控制

    菜單是對路由的直接體現,菜單控制實際上就是路由控制。實現路由控制一個簡單的方式是,在路由的before鉤子里校驗當前即將跳轉的路由地址是否有權訪問,根據校驗結果決定路由是否放行,偽碼:

    router.beforeEach((to, from, next) => {
     //權限校驗
     let pass = valid(to);
     if(!pass){
     return console.log('無權訪問');
     }
     next();
    });
    

    這種實現方式既簡單又直觀,用于簡單的系統非常合適,但這么做本質上是將所有路由全部注冊了,直接帶來的缺點有兩個:一、如果路由組件不是按需加載的話,應用將加載大量冗余代碼;二、每次跳轉都要遍歷一次完整路由是對計算能力的浪費,對于路由總數較大的應用很不可取。

    理想的實現方式是本地保存完整路由,但并不立即初始化Vue應用,待用戶登錄拿到權限后,用菜單權限篩選出可用路由,再用可用路由初始化Vue應用。也就是說,要將登錄頁獨立出去做成一個單獨的頁面,登錄后將用戶數據保存在本地,再通過url跳轉到Vue應用所在頁面,Vue應用啟動前通過本地用戶數據完成路由篩選,然后初始化Vue應用,偽碼如下:

    //main.js
    let user = sessionStorage.getItem('user');
    if (user) {
     user = JSON.parse(user);
     //篩選得到實際路由
     let fullPath = require('fullPath.js');
     let routes = filter(fullPath, user.menus);
     //創建路由對象
     let router = new Router({routes});
     //生成Vue實例
     new Vue({
     el: '#app',
     router,
     render: h => h(App)
     });
    }else{
     location.href = '/login/';
    }
    

    這樣我們就根據用戶權限生成了一套”定制”路由,這時我們還希望能直接用路由生成導航菜單,常規的路由數據可能無法滿足菜單組件的需求,所以我們可以事先在路由的meta數據里維護上菜單數據,比如菜單名稱菜單圖標等,只要在模板中通過$router.options就可以訪問到當前路由數據,如果使用element-ui的菜單組件實現,代碼大致是這樣的:

    <el-menu router>
     <el-menu-item v-for="(route, index) in $router.options.routes[2].children"
     :route="route"
     :index="route.name">
     <i class="ion" v-html="route.icon"></i>{{route.name}}
     </el-menu-item>
    </el-menu>

    當然這樣只能循環出一級菜單,如果還有二級路由需要對應二級菜單的話,就得判斷并循環children節點,比較簡單就不放更多代碼了,菜單權限控制到這里就完成了。

    Vue按鈕權限控制

    按鈕權限控制與菜單權限控制的實現思路類似,也是根據用戶權限判斷各個按鈕的顯示與否,方式無非是v-if或自定義指令,而且只要將v-if背后的權限校驗邏輯抽象成方法,無論是代碼量還是使用形式上都跟自定義指令幾乎一樣,但v-if的特點是它會響應數據變化,因此隨著應用的運行會頻繁觸發權限校驗,而權限在應用的整個生命周期內其實只需校驗一次,為了避免無謂的程序執行,這里可以用自定義指令來實現,偽碼:

    Vue.directive('has', {
     bind: function (el, binding) {
     if(!has(binding.value)){
     el.parentNode.removeChild(el);
     }
     }
    });
    
    //用法:
    <btn v-has='get,/sources'>按鈕</btn>
    

    注意在指令bind回調里有一個has()方法,這就是權限校驗方法,我們同時將這個方法全局混合到Vue對象中,使應用里的每個組件都可以訪問到這個方法,便于為界面上的v-if提供支持,例如:

    <div v-if="has('get,/sources') && something">
     一個需要同時具備'get,/sources'權限和somthing為真值才顯示的div
    </div>

    這樣一來凡是需要依據權限實現的按鈕顯隱控制和界面變化都可以很方便的實現。

    但按鈕權限控制真正麻煩的地方不在于如何實現,而在于高昂的維護成本。我們假設按鈕Btn綁定了點擊回調Fn,回調Fn里發起了請求Req,請求Req需要某個資源的訪問權限,最終你要根據用戶是否擁有Req的權限,決定Btn是否顯示,而Req跟Btn之間并沒有直接關聯,所以我們就要人肉維護他們的關系,一個復雜項目里的按鈕有個幾十上百都很正常,隨著業務的變更去維護這么多按鈕的權限,想想都頭疼。

    有一個方法可以繞開這個爛攤子,那就是前端放棄對視圖層的控制,退到請求層面,在請求發起前集中攔截,這時可以直接根據請求方法和請求地址來校驗權限,除了實現一個攔截器之外不需要額外的代碼,可以說非常優雅了。以axios為例,攔截器大概長這樣:

    axios.interceptors.request.use(function (config) {
     if(!has(config)){
     //驗證不通過
     return Promise.reject({
     message: `no permission`
     });
     }
     return config;
    });
    

    但如果僅僅這樣做權限控制,界面上將顯示出所有的按鈕,用戶看到的按鈕卻不一定可以點擊,這種體驗我認為只能停留在理論層面,根本無法應用到實際產品中。請求控制可以作為整個控制體系的第二道防線,或某些特殊情況下的輔助手段,最終還是要回到按鈕控制的思路上來。

    那么怎樣能盡可能方便的采集到每個按鈕所需的權限呢?按鈕和權限之間隔著兩層東西,第一層是click回調,第二層是回調里的AJAX請求,不想人肉維護就得想辦法突破這兩層隔閡,讓按鈕和權限產生聯系,按鈕必然要綁定click事件,最理想的采集方式是在綁定事件的同時得到所需權限,讓一切自然而然的發生,比如這樣,

    <btn v-do="Fn">按鈕</btn>

    如果Fn能以某種形式采集到內部的AJAX請求參數,并轉化成權限信息傳遞出來就完美了,然而我沒找到可行的方法,并且這種形式在應用上也存在缺陷,因為不一定每個操作按鈕都會發起AJAX請求,比如編輯按鈕本身并不會觸發請求,真正觸發請求的是另一個保存按鈕,所以這個思路只是看起來很美。

    那么退而求其次的做法是讓按鈕和請求聯系起來,比如說按鈕涉及一個名稱為A的請求,那么我希望權限指令可以這樣寫,

    <btn v-has="A" @click="Fn">按鈕</btn>
    

    比完美形態是差了不少,但起碼不需要手動維護到'get,/resources'這個級別了,這里對A的實現可以有多種形式,比如A可以是一個包含兩個屬性的對象:

    const A = {
     p: ['put,/menu/**'],
     r: params => {
     return axios.put(`/menu/${params.id}`, params)
     }
    };
    
    //用作權限:
    <btn v-has="[A]" @click="Fn">按鈕</btn>
    //用作請求:
    function Fn(){
     A.r().then((res) => {})
    }
    
    

    通常我們會將項目里所有的api放在一個api模塊里集中管理,在寫api時順便就把權限給維護了,換來的是在組件界面里可以直接用請求名稱來描述權限,而不需要來回奔波于界面和api模塊之間,一定程度上實現了關注點分離,而且has指令還可以進一步做優化,例如參數只需要接收A,指令內部根據約定自動訪問A.p來獲取權限,還可以接收數組,允許多個權限聯合校驗。

    后記

    好了,這就是我對前端權限控制的一些實踐和思考,如有不當歡迎指正。

    最后吐槽一下Element-UI,真心難看。

    感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!

    聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

    文檔

    基于Vue實現后臺系統權限控制的示例代碼

    基于Vue實現后臺系統權限控制的示例代碼:用Vue/React這類雙向綁定框架做后臺系統再適合不過,后臺系統相比普通前端項目除了數據交互更頻繁以外,還有一個特別的需求就是對用戶的權限控制,那么如何在一個Vue應用中實現權限控制呢?下面是我的一點經驗。 權限控制是什么 在權限的世界里服務端提供的一
    推薦度:
    標簽: VUE 實現 代碼
    • 熱門焦點

    最新推薦

    猜你喜歡

    熱門推薦

    專題
    Top
    主站蜘蛛池模板: 国产亚洲精品资源在线26u| 国产精品一二二区| 久久精品免费观看| 在线精品无码字幕无码AV| 国产精品美女网站在线观看| 国产精品免费无遮挡无码永久视频| 精品无码国产自产拍在线观看蜜| 久久精品国产秦先生| 国产精品亚洲片在线| 亚洲精品午夜无码电影网| 国产一在线精品一区在线观看| 国产精品一级香蕉一区| 国产办公室秘书无码精品99| 宅男在线国产精品无码| 久久久精品人妻无码专区不卡| 2024国产精品极品色在线| 国产成人精品午夜福利| 亚洲精品乱码久久久久久久久久久久| 久久精品不卡| 精品人妻少妇一区二区三区不卡 | 午夜精品久久久久久影视777| 国产精品无码久久久久| 91精品国产麻豆国产自产在线| 精品久久777| 精品国产_亚洲人成在线高清| 99精品在线播放| 国产成人A人亚洲精品无码| 国产美女久久精品香蕉69| 久久Av无码精品人妻系列| 午夜精品射精入后重之免费观看 | 午夜精品久久久久久久无码| 欧美激情精品久久久久久| 老司机精品影院91| 欧美精品福利视频一区二区三区久久久精品| 国产在线精品一区二区高清不卡 | 亚洲精品无码专区久久久| 中国国产精品| 亚洲高清专区日韩精品| 一本一本久久A久久综合精品| 亚洲高清国产拍精品26U| 久久久一本精品99久久精品88|