詳解vue身份認證管理和租戶管理

概述

功能模塊的開發往往是最容易的,但是要處理好每個細節就不容易瞭。就拿這裡的身份認證管理模塊來說,看似很簡單,因為後端接口都是ABP模板裡現成的,前端部分無非就是寫界面,調接口,綁數據;但是看一下ABP Angular版本的代碼,就會發現他其實是有很多細節方面的處理的。

回到vue,因為前端部分的代碼文件太多,下面隻列出一些需要註意的細節,其他的像vue組件、表格、表單、數據綁定、接口請求之類的其實都差不多就不說瞭。

按鈕級權限

前面章節中實現瞭菜單權限的控制,按鈕權限的道理也是一樣的。判斷abpConfig.auth.grantedPolicies是否包含某個權限,然後在組件中使用v-if渲染就好瞭。

src\utils\abp.js:

export function checkPermission(policy) {
  const abpConfig = store.getters.abpConfig;
  if (abpConfig.auth.grantedPolicies[policy]) {
    return true;
  } else {
    return false;
  }
}

src\views\identity\roles.vue:

<el-button
  class="filter-item"
  style="margin-left: 10px;"
  type="primary"
  icon="el-icon-edit"
  @click="handleCreate"
  v-if="checkPermission('AbpIdentity.Roles.Create')"
>
  {{ $t("AbpIdentity['NewRole']") }}
</el-button>

身份認證管理

角色和用戶的增刪改查就不說瞭,這裡要註意一下權限管理。用戶和角色都需要用到權限管理,在ABP Angular版中是一個獨立的permission-management模塊。我這裡也把他作為一個公用組件,根據providerName來區分,”R”是角色權限,”U”是用戶權限。

R/U權限

他們有一點區別,用戶權限可能來自於角色權限,所以用戶中的權限需要顯示是來自哪個providerName和providerKey,如果來自其他provider則disabled,不可以修改。

src\views\identity\components\permission-management.vue:

<el-form label-position="top">
  <el-tabs tab-position="left">
    <el-tab-pane
      v-for="group in permissionData.groups"
      :key="group.name"
      :label="group.displayName"
    >
      <el-form-item :label="group.displayName">
        <el-tree
          ref="permissionTree"
          :data="transformPermissionTree(group.permissions)"
          :props="treeDefaultProps"
          show-checkbox
          check-strictly
          node-key="name"
          default-expand-all
        />
      </el-form-item>
    </el-tab-pane>
  </el-tabs>
</el-form>
transformPermissionTree(permissions, name = null) {
  let arr = [];
  if (!permissions || !permissions.some(v => v.parentName == name))
    return arr;
  const parents = permissions.filter(v => v.parentName == name);
  for (let i in parents) {
    let label = '';
    if (this.permissionsQuery.providerName == "R") {
      label = parents[i].displayName;
    } else if (this.permissionsQuery.providerName == "U") {
      label =
        parents[i].displayName +
        " " +
        parents[i].grantedProviders.map(provider => {
          return `${provider.providerName}: ${provider.providerKey}`;
        });
    }
    arr.push({
      name: parents[i].name,
      label,
      disabled: this.isGrantedByOtherProviderName(
        parents[i].grantedProviders
      ),
      children: this.transformPermissionTree(permissions, parents[i].name)
    });
  }
  return arr;
},
isGrantedByOtherProviderName(grantedProviders) {
  if (grantedProviders.length) {
    return (
      grantedProviders.findIndex(
        p => p.providerName !== this.permissionsQuery.providerName
      ) > -1
    );
  }
  return false;
}

權限刷新

還有一個細節問題,如果正在修改的權限影響到瞭當前用戶,如何立即生效。

src\views\identity\components\permission-management.vue:

updatePermissions(this.permissionsQuery, { permissions: tempData }).then(
  () => {
    this.dialogPermissionFormVisible = false;
    this.$notify({
      title: this.$i18n.t("HelloAbp['Success']"),
      message: this.$i18n.t("HelloAbp['SuccessMessage']"),
      type: "success",
      duration: 2000
    });
    fetchAppConfig(
      this.permissionsQuery.providerKey,
      this.permissionsQuery.providerName
    );
  }
);

src\utils\abp.js:

function shouldFetchAppConfig(providerKey, providerName) {
  const currentUser = store.getters.abpConfig.currentUser;

  if (providerName === "R")
    return currentUser.roles.some(role => role === providerKey);

  if (providerName === "U") return currentUser.id === providerKey;

  return false;
}
export function fetchAppConfig(providerKey, providerName) {
  if (shouldFetchAppConfig(providerKey, providerName)) {
    store.dispatch("app/applicationConfiguration").then(abpConfig => {
      resetRouter();

      store.dispatch("user/setRoles", abpConfig.currentUser.roles);

      const grantedPolicies = abpConfig.auth.grantedPolicies;

      // generate accessible routes map based on grantedPolicies
      store
        .dispatch("permission/generateRoutes", grantedPolicies)
        .then(accessRoutes => {
          // dynamically add accessible routes
          router.addRoutes(accessRoutes);
        });

      // reset visited views and cached views
      //store.dispatch("tagsView/delAllViews", null, { root: true });
    });
  }
}

還有很多需要註意的,比如isStatic===true的角色不可以刪除,並且不可以修改名稱;新增用戶和編輯用戶的密碼校驗規則需要區別對待;保存權限是差異保存。等等。。。有條件的可以看一下ABP的Angular代碼。

租戶管理

基本功能界面都差不多。。。但是這裡有一個”管理功能“的選項,默認是顯示”沒有可用的功能“:

這玩意在界面上沒地方添加,也沒地方刪除,但是這個功能相當實用。它來自ABP的FeatureManagement模塊,也稱為”特征管理“,這個後面再做介紹。

租戶切換

完成瞭租戶管理,那麼登錄時也應該可以切換租戶。

切換租戶比較簡單,就是根據輸入的租戶名稱獲取到租戶ID,然後調用/abp/application-configuration接口,把租戶ID放到請求Header的__tenant字段中即可,之後的請求中也需要這個參數,不傳的話就是默認的宿主端。

其實ABP後端是可以配置是否啟用多租戶的,這裡也可以根據後端配置來顯示或者隱藏租戶切換的按鈕。跟ABP模板相比,登錄界面還缺少一個註冊入口,後面再加上吧。

效果

最後

前端部分的模塊開發就不再詳細介紹瞭,主題還是ABP。進行到這裡,ABP模板自帶的前端部分功能就差不多完成瞭,需要代碼的可以去 https://github.com/xiajingren/HelloAbp 拉取,後面我再把文件整理一下,弄一個幹凈的vue版本。

以上就是詳解vue身份認證管理和租戶管理的詳細內容,更多關於vue身份認證管理和租戶管理的資料請關註WalkonNet其它相關文章!

推薦閱讀: