真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

nodejsacl的用戶權(quán)限管理詳解

說明

創(chuàng)新互聯(lián)公司長期為超過千家客戶提供的網(wǎng)站建設(shè)服務(wù),團隊從業(yè)經(jīng)驗10年,關(guān)注不同地域、不同群體,并針對不同對象提供差異化的產(chǎn)品和服務(wù);打造開放共贏平臺,與合作伙伴共同營造健康的互聯(lián)網(wǎng)生態(tài)環(huán)境。為金臺企業(yè)提供專業(yè)的網(wǎng)站建設(shè)、成都網(wǎng)站建設(shè),金臺網(wǎng)站改版等技術(shù)服務(wù)。擁有十多年豐富建站經(jīng)驗和眾多成功案例,為您定制開發(fā)。

Q: 這個工具用來做什么的呢

A: 用戶有不同的權(quán)限,比如管理員,vip,普通用戶,每個用戶對應(yīng)訪問api,頁面都不一樣

nodejs有兩個比較有名的權(quán)限管理模塊 一個是acl 一個是rbac 綜合對比了一下最終在做項目的時候選擇了acl

功能列表:

  1. addUserRoles //給某用戶添加角色
  2. removeUserRoles //移除某用戶角色
  3. userRoles //獲取某用戶所有角色
  4. roleUsers //獲取所有是此角色的用戶
  5. hasRole // 某用戶是否是某角色
  6. addRoleParents //給某角色增加父角色
  7. removeRoleParents //移除某覺得的某父角色或所有父角色
  8. removeRole //移除某角色
  9. removeResource //移除某資源
  10. allow //給某些角色增加某些資源的某些權(quán)限
  11. removeAllow //移除某些角色的某些資源的某些權(quán)限
  12. allowedPermissions //查詢某人的所有資源及其權(quán)限
  13. isAllowed //查詢某人是否有某資源的某權(quán)限
  14. areAnyRolesAllowed //查詢某角色是否有某資源的某權(quán)限
  15. whatResources //查詢某角色有哪些資源
  16. middleware //middleware for express
  17. backend //指定方式(mongo/redis…)

ACL名詞及其主要方法

roles 角色

  1. removeRole
  2. addRoleParents
  3. allow
  4. removeAllow

resources 資源

  1. whatResources
  2. removeResource

permissions 權(quán)限

users 用戶

  1. allowedPermissions
  2. isAllowed
  3. addUserRoles
  4. removeUserRoles
  5. userRoles
  6. roleUsers
  7. hasRole
  8. areAnyRolesAllowed

使用方法

  1. 建立起配置文件
  2. 用戶登錄后分配相應(yīng)的權(quán)限
  3. 需要控制的地方使用acl做校檢

配置文件

const Acl = require('acl');
const aclConfig = require('../conf/acl_conf');

module.exports = function (app, express) {
  const acl = new Acl(new Acl.memoryBackend()); // eslint-disable-line

  acl.allow(aclConfig);

  return acl;
};

// acl_conf

module.exports = [
  {
    roles: 'normal', // 一般用戶
    allows: [
      { resources: ['/admin/reserve'], permissions: ['get'] },
    ]
  },
  {
    roles: 'member', // 會員
    allows: [
      { resources: ['/admin/reserve', '/admin/sign'], permissions: ['get'] },
      { resources: ['/admin/reserve/add-visitor', '/admin/reserve/add-visitor-excel', '/admin/reserve/audit', '/admin/sign/ban'], permissions: ['post'] },
    ]
  },
  {
    roles: 'admin',  // 管理
    allows: [
      { resources: ['/admin/reserve', '/admin/sign', '/admin/set'], permissions: ['get'] },
      { resources: ['/admin/set/add-user', '/admin/set/modify-user'], permissions: ['post'] },
    ]
  },
  {
    roles: 'root', // 最高權(quán)限
    allows: [
      { resources: ['/admin/reserve', '/admin/sign', '/admin/set'], permissions: ['get'] },
    ]
  }
];

校檢

這里是結(jié)合express做校檢...結(jié)果發(fā)現(xiàn)acl自己提供的中間件太雞肋了,這里就重寫了一個。

function auth() {
    return async function (req, res, next) {
      let resource = req.baseUrl;
      if (req.route) { // 正常在control中使用有route屬性 但是使用app.use則不會有
        resource = resource + req.route.path;
      }
      console.log('resource', resource);

      // 容錯 如果訪問的是 /admin/sign/ 后面為 /符號認(rèn)定也為過
      if (resource[resource.length - 1] === '/') {
        resource = resource.slice(0, -1);
      }

      let role = await acl.hasRole(req.session.userName, 'root');

      if (role) {
        return next();
      }

      let result = await acl.isAllowed(req.session.userName, resource, req.method.toLowerCase());
      // if (!result) {
      //   let err = {
      //     errorCode: 401,
      //     message: '用戶未授權(quán)訪問',
      //   };
      //   return res.status(401).send(err.message);
      // }
      next();
    };
  }

有點要說明的是express.Router支持導(dǎo)出一個Router模塊 再在app.use使用,但是如果你這樣使用 app.use('/admin/user',auth(), userRoute); 那么是在auth這個函數(shù)是獲取不到 req.route 這個屬性的。 因為acl對訪問權(quán)限做的是強匹配,所以需要有一定的容錯

登錄的權(quán)限分配

result為數(shù)據(jù)庫查詢出來的用戶信息,或者后臺api返給的用戶信息,這里的switch可以使用配置文件的形式,因為我這邊本次項目只有三個權(quán)限,所以就在這里簡單寫了一下。

let roleName = 'normal';

  switch (result.result.privilege) {
    case 0:
      roleName = 'admin';
      break;
    case 1:
      roleName = 'normal';
      break;
    case 2:
      roleName = 'member';
      break;
  }

  if (result.result.name === 'Nathan') {
    roleName = 'root';
  }

  req.session['role'] = roleName;
  // req.session['role'] = 'root';  // test
  acl.addUserRoles(result.result.name, roleName);
  // acl.addUserRoles(result.result.name, 'root'); // test

pug頁面中的渲染邏輯控制

在 express+pug中 app.locals.auth= async function(){} 這個寫法在pug渲染的時候是不會得出最終結(jié)果的,因為pug是同步的,那么我如何控制當(dāng)前頁面或者說當(dāng)前頁面的按鈕用戶是否有權(quán)限展示出來, 這里通用的做法有

  1. 用戶在登錄的時候有一個路由表和組件表 然后在渲染的時候 根據(jù)這個表去渲染
  2. 在需要權(quán)限控制的地方,使用函數(shù)來判斷用戶是否有權(quán)限訪問

我這里采用的是結(jié)局方案2.因為比較方便, 但是問題來了 express+pug是不支持異步的寫法,而acl提供給我們的全是異步的, 因為時間原因,我沒有去深究里面的判斷,而是采用了一種耦合性比較高但是比較方便的判斷方法.

app.locals.hasRole = function (userRole, path, method = 'get') {

  if (userRole === 'root') {
    return true;
  }

  const current = aclConf.find((n) => {
    return n['roles'] === userRole;
  });

  let isFind = false;
  for (let i of current.allows) {
    const currentPath = i.resources; // 目前數(shù)組第一個為單純的get路由
    isFind = currentPath.includes(path);

    if (isFind) {
      // 如果找到包含該路徑 并且method也對應(yīng)得上 那么則通過
      if (i.permissions.includes(method)) {
        break;
      }

      // 如果找到該路徑 但是method對應(yīng)不上 則繼續(xù)找.
      continue;
    }
  }

  return isFind;
};

上述代碼頁比較簡單, 去遍歷acl_conf,查找用戶是否有當(dāng)前頁面的或者按鈕的權(quán)限 因為acl_conf在加載的時候就已經(jīng)被寫入內(nèi)存了,所以性能消耗不會特別大。比如下面的例子。

if hasRole(user.role, '/admin/reserve/audit', 'post')
          .col.l3.right-align
            a.waves-effect.waves-light.btn.margin-right.blue.font12.js-reviewe-ok 同意
            a.waves-effect.waves-light.btn.pink.accent-3.font12.js-reviewe-no 拒絕

結(jié)尾

依靠acl這個組件可以快速打造一個用戶的權(quán)限管理模塊。 但是還有個問題 也急速那個app.locals.hasRole函數(shù), 如果你使用removeAllow動態(tài)改變了用戶的權(quán)限表,那么hasRole函數(shù)就很麻煩了。 所以在這種情況下 有以下幾個解決方案

  1. 從acl源碼入手
  2. 每次渲染的時候就把數(shù)據(jù)準(zhǔn)備好
const hasBtn1Role = hasRole(user.role, '/xxx','get');
res.render('a.pug',{hasBtn1Role})

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持創(chuàng)新互聯(lián)。


標(biāo)題名稱:nodejsacl的用戶權(quán)限管理詳解
路徑分享:http://weahome.cn/article/iejhsd.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部