<font id="zqva1"></font>
<rt id="zqva1"></rt>
  • <tt id="zqva1"></tt>
    <cite id="zqva1"></cite>

    <cite id="zqva1"><noscript id="zqva1"></noscript></cite>
      <rp id="zqva1"><meter id="zqva1"></meter></rp>

        <cite id="zqva1"></cite>
          <b id="zqva1"></b>
          <rp id="zqva1"></rp>
          <cite id="zqva1"></cite>

          <rt id="zqva1"></rt>

        1. <rp id="zqva1"></rp>

          Vue2.0用戶權限控制解決方案

          時間:?2017-11-29閱讀:?1192標簽:?vue作者:?前端路上

          Vue-Access-Control是一套基于Vue/Vue-Router/axios 實現的前端用戶權限控制解決方案,通過對路由、視圖、請求三個層面的控制,使開發者可以實現任意顆粒度的用戶權限控制。

          安裝

          版本要求

          Vue 2.0x

          Vue-router 3.x

          獲取

          項目主頁:http://refined-x.com/Vue-Access-Control/

          git:git clone https://github.com/tower1229/Vue-Access-Control.git
          npm:npm i vue-access-control


          運行

          //開發
          npm run dev
          //構建
          npm build


          概述

          整體思路

          會話開始之初,先初始化一個只有登錄路由的Vue實例,在根組件created鉤子里將路由定向到登錄頁,用戶登錄成功后前端拿到用戶token,設置axios實例統一為請求headers添加{"Authorization":token}實現用戶鑒權,然后獲取當前用戶的權限數據,主要包括路由權限和資源權限,之后動態添加路由,生成菜單,實現權限指令和全局權限驗證方法,并為axios實例添加請求攔截器,至此完成權限控制初始化。動態加載路由后,路由組件將隨之加載并渲染,而后展現前端界面。

          為解決瀏覽器刷新路由重置的問題,拿到token后要將其保存到sessionStorage,根組件的created鉤子負責檢查本地是否已有token,如果有則無需登錄直接用該token獲取權限并初始化,如果token有效且當前路由有權訪問,將加載路由組件并正確展現;若當前路由無權訪問將按路由設置跳轉404;如果token失效,后端應返回4xx狀態碼,前端統一為axios實例添加錯誤攔截器,遇到4xx狀態碼執行退出操作,清除sessionStorage數據并跳轉到登錄頁,讓用戶重新登錄。

          最小依賴原則

          Vue-Access-Control的定位是單一領域解決方案,除了Vue/Vue-Router/axios之外沒有其他依賴,理論上可以無障礙的應用到任何有權限控制需求的Vue項目中,項目基于webpack 模板開發構建,大多數新項目可以直接基于檢出代碼繼續開發。需要說明的是,項目額外引入的Element-UICryptoJS僅用于開發演示界面,他們不是必須且與權限控制毫無關系,項目應用中可以自行取舍。

          目錄結構

          src/
            |-- api/                  //接口文件
            |     |-- index.js             //輸出通用axios實例
            |     |-- account.js           //按業務模塊組織的接口文件,所有接口都引用./index提供的axios實例
            |-- assets/
            |-- components/
            |-- router/
            |     |-- fullpath.js         //完整路由數據,用于匹配用戶的路由權限得到實際路由
            |     `-- index.js            //輸出基礎路由實例
            |-- views/
            |-- App.vue
            ·-- main.js


          數據格式約定

          路由權限數據必須是如下格式的對象數組,id和parent_id相同的兩個路由具有上下級關系,如果希望使用自定義格式的路由數據,需要修改路由控制的相關實現,詳見路由控制

          [
              {
                "id": "1",
                "name": "菜單1",
                "parent_id": null,
                "route": "route1"
              },
              {
                "id": "2",
                "name": "菜單1-1",
                "parent_id": "1",
                "route": "route2"
              }
            ]


          資源權限數據必須是如下格式的對象數組,每個對象代表一個RESTful請求,支持帶參數的url,具體格式說明見請求控制

          [
              {
                "id": "2c9180895e172348015e1740805d000d",
                "name": "賬號-獲取",
                "url": "/accounts",
                "method": "GET"
              },
              {
                "id": "2c9180895e172348015e1740c30f000e",
                "name": "賬號-刪除",
                "url": "/account/**",
                "method": "DELETE"
              }
          ]


          路由控制

          路由控制包括動態注冊路由和動態生成菜單兩部分。

          動態注冊路由

          最初實例化的路由僅包括登錄和404兩個路徑,我們期待完整的路由是這樣的:

          [{
            path: '/login',
            name: 'login',
            component: (resolve) => require(['../views/login.vue'], resolve)
          }, {
            path: '/404',
            name: '404',
            component: (resolve) => require(['../views/common/404.vue'], resolve)
          }, {
            path: '/',
            name: '首頁',
            component: (resolve) => require(['../views/index.vue'], resolve),
            children: [{
              path: '/route1',
              name: '欄目1',
              meta: {
                icon: 'icon-channel1'
              },
              component: (resolve) => require(['../views/view1.vue'], resolve)
            }, {
              path: '/route2',
              name: '欄目2',
              meta: {
                icon: 'ico-channel2'
              },
              component: (resolve) => require(['../views/view2.vue'], resolve),
              children: [{
                path: 'child2-1',
                name: '子欄目2-1',
                meta: {
                  
                },
                component: (resolve) => require(['../views/route2-1.vue'], resolve)
              }]
            }]
          }, {
            path: '*',
            redirect: '/404'
          }]


          那么接下來就需要獲取首頁以及其子路由們,思路是事先在本地存一份整個項目的完整路由數據,然后根據用戶權限對完整路由進行篩選。

          篩選的實現思路是先將后端返回的路由數據處理成如下哈希結構:

          let hashMenus = {
             "/route1":true,
             "/route1/route1-1":true,
             "/route1/route1-2":true,
             "/route2":true,
             ...
          }


          然后遍歷本地完整路由,在循環中將路徑拼接成上述結構中的key格式,通過hashMenus[route]就可以判斷路由是否匹配,具體實現見App.vue文件中的getRoutes()方法。

          如果后端返回的路由權限數據與約定不同,就需要自行實現篩選邏輯,只要能得到實際可用的路由數據就可以,最終使用addRoutes()方法將他們動態添加到路由實例中,注意404頁面的模糊匹配一定要放在最后。

          動態菜單

          路由數據可以直接用來生成導航菜單,但路由數據是在根組件中得到的,導航菜單存在于index.vue組件中,顯然我們需要通過某種方式共享菜單數據,方法有很多,一般來說首先想到的是Vuex,但菜單數據在整個用戶會話過程中不會發生改變,這并不是Vuex的最佳使用場景,而且為了盡量減少不必要的依賴,這里用了最簡單直接的方法,把菜單數據掛在根組件data.menuData上,在首頁里用this.$parent.menuData獲取。

          另外,導航菜單很可能會有添加欄目圖標的需求,這可以通過在路由中添加meta數據實現,例如將圖標class或unicode存到路由meta里,模板中就可以訪問到meta數據,用來生成圖標標簽。

          在多角色系統中可能遇到的一個問題是,不同角色有一個名字相同但功能不同的路由,比如說系統管理員企業管理員都有”賬號管理”這個路由,但他們的操作權限和目標不同,實際上是兩個完全不同的界面,而Vue不允許多個路由同名,因此路由的name必須做區分,但把區分后的name顯示在前端菜單上會很不美觀,為了讓不同角色可以享有同一個菜單名稱,我們只要將這兩個路由的meta.name都設置成”賬號管理”,在模板循環時優先使用meta.name就可以了。

          菜單的具體實現可以參考views/index.vue。

          視圖控制

          視圖控制的目標是根據當前用戶權限決定界面元素顯示與否,典型場景是對各種操作按鈕的顯示控制。實現視圖控制的本質是實現一個權限驗證方法,輸入請求權限,輸出是否獲準。然后配合v-if或jsx或自定義指令就能靈活實現各種視圖控制。

          全局驗證方法

          驗證方法的的實現本身很簡單,無非是根據后端給出的資源權限做判斷,重點在于優化方法的輸入輸出,提升易用性,經過實踐總結最終使用的方案是,將權限跟請求同時維護,驗證方法接收請求對象數組為參數,返回是否具有權限的布爾值。

          請求對象格式:

          //獲取賬戶列表
          const request = {
            p: ['get,/accounts'],
            r: params => {
              return instance.get(`/accounts`, {params})
            }
          }


          權限驗證方法$_has()的調用格式:

          v-if="$_has([request])"


          權限驗證方法的具體實現見App.vue中Vue.prototype.$_has方法。

          將權限驗證方法全局混入,就可以在項目中很容易的配合v-if實現元素顯示控制,這種方式的優點在于靈活,除了可以校驗權限外,還可以在判斷表達式中加入運行時狀態做更多樣性的判斷,而且可以充分利用v-if響應數據變化的特點,實現動態視圖控制。

          具體實現細節參考基于Vue實現后臺系統權限控制中的相關章節。

          自定義指令

          v-if的響應特性是把雙刃劍,因為判斷表達式在運行過程中會頻繁觸發,但實際上在一個用戶會話周期內其權限并不會發生變化,因此如果只需要校驗權限的話,用v-if會產生大量不必要的運算,這種情況只需在視圖載入時校驗一次即可,可以通過自定義指令實現:

          //權限指令
          Vue.directive('has', {
            bind: function(el, binding) {
              if (!Vue.prototype.$_has(binding.value)) {
                el.parentNode.removeChild(el);
              }
            }
          });


          自定義指令內部仍然是調用全局驗證方法,但優點在于只會在元素初始化時執行一次,多數情況下都應該使用自定義指令實現視圖控制。

          請求控制

          請求控制是利用axios攔截器實現的,目的是將越權請求在前端攔截掉,原理是在請求攔截器中判斷本次請求是否符合用戶權限,以決定是否攔截。

          普通請求的判斷很容易,遍歷后端返回的的資源權限格式,直接判斷request.method和request.url是否吻合就可以了,對于帶參數的url需要使用通配符,這里需要根據項目需求前后端協商一致,約定好通配符格式后,攔截器中要先將帶參數的url處理成約定格式,再判斷權限,方案中已經實現了以下兩種通配符格式:

          1. 格式:/resources/:id
             示例:/resources/1
             url: /resources/**
             解釋:一個名詞后跟一個參數,參數通常表示名詞的id
             
          2. 格式:/store/:id/member
             示例:/store/1/member
             url:/store/*/member
             解釋:兩個名詞之間夾帶一個參數,參數通常表示第一個名詞的id


          對于第一種格式需要注意的是,如果你要發起一個url為"/aaa/bbb"的請求,默認會被處理成"/aaa/**"進行權限校驗,如果這里的”bbb”并不是參數而是url的一部分,那么你需要將url改成"/aaa/bbb/",在最后加一個”/“表示該url不需要轉化格式。

          攔截器的具體實現見App.vue中的setInterceptor()方法。

          如果你的項目還需要其他的通配符格式,只需要在攔截器中實現對應的檢測和轉化方法就可以了。

          演示及說明

          演示說明:

          DEMO項目中演示了動態菜單、動態路由、按鈕權限、請求攔截。

          演示項目后端由rap2生成mock數據,登錄請求通常應該是POST方式,但因為rap2的編程模式無法獲取到非GET的請求參數,因此只能用GET方式登錄,實際項目中不建議仿效;

          另外登錄后獲取權限的接口本來不需要攜帶額外參數,后端可以根據請求頭攜帶的token信息實現用戶鑒權,但因為rap2的編程模式獲取不到headers數據,因此只能增加一個”Authorization”參數用于生成模擬數據。

          測試賬號:

          1. username: root
             password: 任意
          2. username: client
             password: 任意


          演示地址:

          vue-access-control.refined-x.com

          轉載請注明出處:http://refined-x.com/2017/11/28/Vue2.0用戶權限控制解決方案/

          吐血推薦

          1.站長廣告聯盟: 整理了目前主流的廣告聯盟平臺,如果你有流量,可以作為參考選擇適合你的平臺點擊進入...

          2.休閑娛樂: 直播/交友    優惠券領取   網頁游戲   H5游戲

          鏈接: http://www.modern-decoration.com.cn/article/detial/190

          Vue 的 .sync 修飾符

          .sync 修飾符算是 Vue 的所有修飾符中較難理解的一個,本篇文章就帶你走近 .sync 的世界,深入理解后會發現,其實也就那么回事。修飾符和指令息息相關,下面從 指令 -> 修飾符 -> .sync 修飾符 由淺入深地來講解 .sync 的含義及用法。

          vue中is的作用和用法

          總所周知,ul里面嵌套li的寫法是html語法的固定寫法(還有如table,select等)。my-component是我們自己寫的組件,但是html在渲染dom的時候,my-component對ul來說并不是有效的dom,甚至會報錯。

          一點 Vue.observable 想法

          Vue 2.6.0 新增了 Vue.observable api,但最近才去嘗試使用它。這東西說新也不新,因為他就是 vue 本身的功能,只是暴露出來,成為新 api 了。在老版本中,直接用 new Vue({ data: {} }) 也一樣。

          Vue.use到底是什么?

          我們在使用Vue做項目開發的時候,看到不少輪子都是通過Vue.use來進行使用,感覺甚是高大上。不過Vue.use到底是什么鬼?不妨來看個究竟。

          Vue.js最佳實踐:五招讓你成為Vue.js大師

          本文面向對象是有一定Vue.js編程經驗的開發者。如果有人需要Vue.js入門系列的文章可以在評論區告訴我,有空就給你們寫。對大部分人來說,掌握Vue.js基本的幾個API后就已經能夠正常地開發前端網站

          vue介紹

          庫是一種插件,是一種封裝好的特定方法的集合。提供給開發者使用,控制器在使用者手里。框架是一套架構,會基于自身特定向用戶提供一套相當完整的解決方案,控制權在框架本身

          vue有時候你不需要 $emit & $on

          在此之前,子組件到父組件的傳遞事件我一般還是使用 $emit 和 $on,因為這個操作理解起來并不難,代碼一般也挺清晰。不過今天遇到這么個情況 ——

          Vue最佳實踐

          Vue 最佳實踐,是參考 Vue 官方風格指南并根據過去 Vue 實際項目開發中的經驗總結的一套規范建議。本項目的目的是希望每個 Vue 開發者都能盡快熟悉并上手項目代碼,志在幫助 Vue 新手開發者及時避免一些不規范的設計和由此而引發的問題

          vue知識點總匯

          keep-alive它是vue的內置組件在默認情況下,v-model 在每次 input 事件觸發后將輸入框的值與數據進行同步 。你可以添加 lazy 修飾符,從而轉變為使用 change 事件進行同步:

          vue中使用v-for時為什么不能用index作為key?

          Vue 和 React 都實現了一套虛擬DOM,使我們可以不直接操作DOM元素,只操作數據便可以重新渲染頁面。而隱藏在背后的原理便是其高效的Diff算法。Vue 和 React 的虛擬DOM的Diff算法大致相同,其核心是基于兩個簡單的假設

          fly63.com版權所有,內容以共享、參考、研究為目的,不存在任何商業目的。其版權屬原作者所有,如有侵權,請與小編聯系!情況屬實本人將予以刪除!

          文章投稿關于web前端網站點搜索站長推薦網站地圖站長QQ:522607023

          小程序專欄: 土味情話心理測試腦筋急轉彎幽默笑話段子句子語錄成語大全

          国产精品高清视频免费 - 视频 - 在线观看 - 影视资讯 - 唯爱网