Vue 前端應用實現RBAC權限控制的一種方式

上午發佈前,感受已經作完了,就接着擼jiiiiiin權限系統 ,但是我發現漏了一個東西,就是一更的時候,針對v-access指令默認模式,經過校驗對應資源所需接口列表來檢查登陸用戶是否具備訪問權限,可是那個時候的對比是接口的url,數據結構以下:html

authorizeInterfaces:前端

["admin/dels/*", "admin/search/*/*/*", "admin/*/*/*", "role/list/*", "admin/*"]
複製代碼

可是我接着寫的時候,發現不知足呀,我後臺的接口是RESTful類型的,因此必須校驗url+method,那如今的數據結構就變成:vue

authorizeInterfaces:git

[{url: "admin/dels/*", method: "DELETE"}, ....]
複製代碼

故由修改了一下,具體能夠參考下面的commit:github

修改rbac前端校驗模塊,使其支持RESTful類型接口校驗 ajax

對於使用就兩步: 1.增長了一個isRESTfulInterfaces配置:正則表達式

/** * [*] 聲明`authorizeInterfaces`集合存儲的是RESTful類型的接口仍是常規接口 * 1. 若是是(true),則`authorizeInterfaces`集合須要存儲的結構就是: * [{url: 'admin/dels/*', method: 'DELETE'}] * 即進行接口匹配的時候會校驗類型 * 2. 若是不是(false),則`authorizeInterfaces`集合須要存儲的結構就是,即不區分接口類型: * ['admin/dels/*'] */
    isRESTfulInterfaces = true
複製代碼

2.在登陸成功設置$vp.rabcUpdateAuthorizeInterfaces已受權接口列表的時候,你們須要將數據結構構造好。spring

3.針對於RESTful類型接口:v-access="[{url: 'admin/search/*', method: 'POST'}]"json

如今針對v-access指令的值的使用,能夠有如下幾種狀況:後端

  • 若是isRESTfulInterfaces設置爲true注意這是默認設置,則使用下面的格式:
v-access="[{url: 'admin/search/*', method: 'POST'}]"
// 或者若是隻有一個接口聲明
v-access="{url: 'admin/search/*/*/*', method: 'POST'}"
複製代碼
  • 若是isRESTfulInterfaces設置爲false,則使用下面的格式:
v-access="['admin', 'admin/*']"
複製代碼
  • 若是但願使用別名標識一個資源:
v-access:alias="['LOGIN', 'WELCOME']"
v-access:alias="'LOGIN'"
複製代碼
  • 另外以上幾種都是如何聲明組件所需權限,而若是登陸用戶沒有這個權限,則組件將會被隱藏,可是也可使用下面的配置讓組件變爲半透明且不可用點擊:
v-access:alias.disable="['LOGIN', 'WELCOME']"
v-access.disable="['admin', 'admin/*']"
複製代碼

就是加一個disable而已;

:)

謝謝支持!

更新分割


權限控制無論先後端均可以簡單分爲:

  • 身份認證權限控制
  • RBAC權限控制
  • ...

而前端我和團隊,檢索了不少地方都沒有很成熟或者說可行的關於 RBAC基於角色的訪問控制相關的前端權限控制方案,多是咱們檢索的方法不對,亦或是你們都忙於其餘,沒有時間把本身的方法整理公佈出來,故咱們在原定計劃中,本身實踐了一把,下面和你們分享一下,有不對或者錯誤的地方,望指正。

若是你們點進來,應該都知道何爲RBAC,爲何須要使用了,故這裏對此不作過多解釋,RBAC基於角色的訪問控制,通常只會在管理端應用使用,故這個模塊不做爲默認模塊。

下面介紹一下vue-viewplus 一個簡化Vue應用開發的工具庫中的rabc.js 自定義RBAC權限控制模塊。

該模塊,意在爲前端應用提供rbac權限控制幫助。

其和login-state-check.js 身份認證權限控制模塊不一樣之處在於,該模塊提供了一下兩種權限控制手段:

  • 實現前端頁面可訪問性控制,即經過路由攔截,判斷用戶待訪問頁面是否已經受權
  • 實現可見頁面的局部UI組件的可以使用性或可見性控制,即基於自定義v-access指令,對比聲明的接口或資源別是否已經受權

而login-state-check.js 身份認證權限控制模塊,則提供的是對非公共頁面的身份認證校驗檢查,其中維護了用戶的身份認證即登陸狀態,這種權限控制,更適合大多數應用,即給用戶使用的客戶端應用。

而當前模塊也依賴了登陸狀態,故能夠一塊兒複用;

實際案例:

名稱 渠道 簡介
jiiiiiin權限系統 PC端 一個先後端分離的內管基礎項目,並基於當前插件完成了RBAC前端權限控制

效果以下:

使用方法:

  1. 基於vue-viewplus,實現了一個自定義模塊 ,非標準模塊,須要手動配置:

main.js入口文件:

import router from './router'
import ViewPlus from 'vue-viewplus'
import rbacModule from '@/plugin/vue-viewplus/rbac.js'
import viewPlusOptions from '@/plugin/vue-viewplus'

Vue.use(ViewPlus, viewPlusOptions)

ViewPlus.mixin(Vue, rbacModule, {
    debug: true,
    errorHandler(err) {
        console.error(err)
    },
    moduleName: '自定義RBAC',
    router,
    publicPaths: ['/login'],
    onLoginStateCheckFail(to, from, next) {
        this.dialog(`您無權訪問【${to.path}】頁面`)
            .then(() => {
            // 防止用戶被踢出以後,被權限攔截致使訪問不了任何頁面,故這裏進行登陸狀態監測
            if (this.isLogin()) {
                next(false);
            } else {
                next('/login');
            }
        })
    }
})
複製代碼
  1. 在登陸成功以後,須要設置插件的登陸狀態,和rabc模塊相應權限集合,即後端返回的當前登陸用戶擁有的:
  • [*] 登陸用戶擁有訪問權限的路由path路徑集合

    完成該配置,則頁面可訪問性控制就能夠正常工做

  • [*] 登陸用戶擁有訪問權限的後臺接口集合

  • [可選] 登陸用戶擁有訪問權限的資源別名集合

    完成以上配置,則自定義v-access指令就能夠支持對應模式的配置

  • [可選] 是不是超級用戶

    有些系統存在一個超級用戶角色,其能夠訪問任何資源、頁面,故若是設置,針對這個登陸用戶將不會作任何權限校驗,以便節省前端資源

// 開始請求登陸接口
      AccountLogin(vm.$vp, {
        username,
        password,
        imageCode
      })
        .then(async res => {
          // 修改用戶登陸狀態
          vm.$vp.modifyLoginState(true)
          const menus = _delEmptyChildren(res.principal.admin.menus);
          const authorizeResources = _parseAuthorizePaths(res.principal.admin.authorizeResources);
          vm.$vp.rabcUpdateAuthorizedPaths(authorizeResources)
          const authorizeInterfaces = _parseAuthorizeInterfaces(res.principal.admin.authorizeInterfaces);
          vm.$vp.rabcUpdateAuthorizeInterfaces(authorizeInterfaces)
          const isSuperAdminStatus = _parseUserRoleIsSuperAdminStatus(res.principal.admin.roles);
          vm.$vp.rabcUpdateSuperAdminStatus(isSuperAdminStatus)
複製代碼

針對須要設置的權限集合,其都是扁平化的一維數組,格式相似:

authorizedPathspublicPaths:

["/mngauth/admin", "/index", "/mngauth"]
複製代碼

authorizeInterfaces:

["admin/dels/*", "admin/search/*/*/*", "admin/*/*/*", "role/list/*", "admin/*"]
複製代碼

authorizeResourceAlias:

["MNG_USERMNG", "MNG_ROLEMNG"]
複製代碼

注意以上數組的值除了能夠配置爲字符串還能夠配置爲正則表達式:

[/^((\/Interbus)(?!\/SubMenu)\/.+)$/]
複製代碼
  1. 實現可見頁面的局部UI組件的可以使用性或可見性配置示例:
<el-form v-access="['admin/search/*/*/*']" slot="search-inner-box" :inline="true" :model="searchForm" :rules="searchRules" ref="ruleSearchForm" class="demo-form-inline">
...
	<el-form-item class="search-inner-btn-box">
        <el-button size="small" type="primary" icon="el-icon-search" @click="onSearch">查詢</el-button>
        <el-button size="small" icon="el-icon-refresh" @click="onCancelSubmit">重置</el-button>
      </el-form-item>
</el-form>
複製代碼

完成以上配置便可讓正常使用當前模塊提供的權限控制服務,固然如$vp.modifyLoginState|$vp#isLogin涉及到login-state-check.js 身份認證權限控制模塊

計劃

針對authorizeInterfaces,後期將會用於在發送ajax請求以前,對待請求的接口和當前集合進行匹配,若是匹配失敗說明用戶就沒有請求權限,則直接不發送後臺請求,減小後端沒必要要的資源浪費,在完成這個權限匹配,前端基礎的權限規則就完整了。

其實實現下來沒有想象的那麼複雜,能夠點擊查看源碼

相較於理解這一塊,我以爲理解RBAC原則和表結構,才能更好的理解爲何要這麼控制,更多的關於後端關於這一塊的實踐,能夠參考jiiiiiin權限系統這個內管項目針對表結構的設計,其後臺使用的是spring security來完成後端的RBAC權限控制,並針對當前前端權限須要和vue router path進行了細微變化,相較於傳統的RBAC 金典5張表的設計。

也請你們多多支持 :)

下面是改模塊的api描述:

配置

debug|errorHandler|router|installed配置,能夠查看全局通用配置

publicPaths

/** * [*] 系統公共路由path路徑集合,便可以讓任何人訪問的頁面路徑 * {Array<Object>} * <p> * 好比登陸頁面的path,由於登陸以前咱們是沒法判斷用戶是否能夠訪問某個頁面的,故須要這個配置,固然若是須要這個配置也能夠在初始化插件以前從服務器端獲取,這樣先後端動態性就更高,可是通常沒有這種需求:) * <p> * 數組中的item,能夠是一個**正則表達式字面量**,如`[/^((\/Interbus)(?!\/SubMenu)\/.+)$/]`,也能夠是一個字符串 * <p> * 匹配規則:若是在`LoginStateCheck#publicPaths`**系統公共路由path路徑集合**中,那麼就直接跳過權限校驗 */
publicPaths = []
複製代碼

authorizedPaths

/** * [*] 登陸用戶擁有訪問權限的路由path路徑集合 * {Array<Object>} * <p> * 數組中的item,能夠是一個**正則表達式字面量**,如`[/^((\/Interbus)(?!\/SubMenu)\/.+)$/]`,也能夠是一個字符串 * <p> * 匹配規則:若是在`LoginStateCheck#authorizedPaths`**須要身份認證規則集**中,那麼就須要查看用戶是否登陸,若是沒有登陸就拒絕訪問 */
authorizedPaths = []
複製代碼

authorizeInterfaces

/** * [*] 登陸用戶擁有訪問權限的後臺接口集合 * {Array<Object>} * <p> * 1.在`v-access`指令配置爲url(默認)校驗格式時,將會使用該集合和指令聲明的待審查受權接口列表進行匹配,若是匹配成功,則指令校驗經過,不然校驗不經過,會將對應dom元素進行處理 * 2.TODO 將會用於在發送ajax請求以前,對待請求的接口和當前集合進行匹配,若是匹配失敗說明用戶就沒有請求權限,則直接不發送後臺請求,減小後端沒必要要的資源浪費 * <p> * 數組中的item,能夠是一個**正則表達式字面量**,如`[/^((\/Interbus)(?!\/SubMenu)\/.+)$/]`,也能夠是一個字符串 * <p> * 匹配規則:將會用於在發送ajax請求以前,對待請求的接口和當前集合進行匹配,若是匹配失敗說明用戶就沒有請求權限,則直接不發送後臺請求,減小後端沒必要要的資源浪費 */
    authorizeInterfaces = []
複製代碼

authorizeResourceAlias

/** * [可選] 登陸用戶擁有訪問權限的資源別名集合 * {Array<Object>} * <p> * 數組中的item,能夠是一個**正則表達式字面量**,如`[/^((\/Interbus)(?!\/SubMenu)\/.+)$/]`,也能夠是一個字符串 * <p> * 匹配規則:由於若是都用`LoginStateCheck#authorizeInterfaces`接口進行匹配,可能有一種狀況,訪問一個資源,其須要n個接口,那麼咱們在配置配置權限指令:v-access="[n, n....]"的時候就須要聲明全部須要的接口,就會須要對比屢次, * 當咱們系統的接口集合很大的時候,勢必會成爲一個瓶頸,故咱們能夠爲資源聲明一個別名,這個別名則能夠表明這n個接口,這樣的話就從n+減小到n次匹配; */
authorizeResourceAlias = []
複製代碼

onLoginStateCheckFail

/** * [*] `$vp::onLoginStateCheckFail(to, from, next)` * <p> * 權限檢查失敗時被回調 */
onLoginStateCheckFail = null
複製代碼

API接口

modifyLoginState

/** * 代理`$vp#login-state-check`模塊的同名方法,以實如今登出、會話超時踢出的時候清理本模塊維護的登陸以後設置的狀態 * @param status */
  modifyLoginState(status = false)
複製代碼

rabcUpdateSuperAdminStatus

/** * 【可選】有些系統存在一個超級用戶角色,其能夠訪問任何資源、頁面,故若是設置,針對這個登陸用戶將不會作任何權限校驗,以便節省前端資源 * @param status */
  rabcUpdateSuperAdminStatus(status)
複製代碼

rabcAddAuthorizedPaths

/** * 添加受權路徑集合 * 如:登陸完成以後,將用戶被受權能夠訪問的頁面`paths`添加到`LoginStateCheck#authorizedPaths`中 * @param paths */
  rabcAddAuthorizedPaths(paths)
複製代碼

rabcUpdateAuthorizedPaths

/** * 更新受權路徑集合 * @param paths */
  rabcUpdateAuthorizedPaths(paths)
複製代碼

rabcUpdateAuthorizeResourceAlias

/** * 更新資源別名集合 * @param alias */
  rabcUpdateAuthorizeResourceAlias(alias)
複製代碼

rabcAddAuthorizeResourceAlias

/** * 添加資源別名集合 * @param alias */
  rabcAddAuthorizeResourceAlias(alias)
複製代碼

rabcUpdatePublicPaths

/** * 更新公共路徑集合 * @param paths */
  rabcUpdatePublicPaths(paths)
複製代碼

rabcAddPublicPaths

/** * 添加公共路徑集合 * @param paths */
  rabcAddPublicPaths(paths)
複製代碼

若是你們以爲有用,請你們多多支持,更多的模塊請點擊查看

相關文章
相關標籤/搜索