0

0

nodejs acl的用户权限管理详解

亚连

亚连

发布时间:2018-05-30 11:13:36

|

3042人浏览过

|

来源于php中文网

原创

这篇文章主要介绍了nodejs acl的用户权限管理详解,现在分享给大家,也给大家做个参考。

说明

Q: 这个工具用来做什么的呢

A: 用户有不同的权限,比如管理员,vip,普通用户,每个用户对应访问api,页面都不一样

nodejs有两个比较有名的权限管理模块 一个是acl 一个是rbac 综合对比了一下最终在做项目的时候选择了acl

功能列表:

  1. addUserRoles //给某用户添加角色

  2. removeUserRoles //移除某用户角色

  3. userRoles //获取某用户所有角色

  4. roleUsers //获取所有是此角色的用户

  5. hasRole // 某用户是否是某角色

  6. addRoleParents //给某角色增加父角色

  7. removeRoleParents //移除某觉得的某父角色或所有父角色

  8. removeRole //移除某角色

  9. removeResource //移除某资源

  10. allow //给某些角色增加某些资源的某些权限

  11. removeAllow //移除某些角色的某些资源的某些权限

  12. allowedPermissions //查询某人的所有资源及其权限

  13. isAllowed //查询某人是否有某资源的某权限

  14. areAnyRolesAllowed //查询某角色是否有某资源的某权限

  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 权限

users 用户

  1. allowedPermissions

  2. isAllowed

  3. addUserRoles

  4. removeUserRoles

    NT80 购物系统
    NT80 购物系统

    功能说明:1 会员可申请开店功能2 购买在线扣除金额3 冲值卡自动生成4 支持2级分类5 数据库压缩和备份6 会员分5个级别7 商品带讨论8 自带融合论坛,可关闭打开9 密码找回功能10 新闻``滚动新闻``帮助中心11 后台设置前台会员的上传权限12 可关闭/打开商店13 会员自助发布商品功能14 用户问题咨询管理

    下载
  5. userRoles

  6. roleUsers

  7. hasRole

  8. areAnyRolesAllowed

使用方法

  1. 建立起配置文件

  2. 用户登录后分配相应的权限

  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', // 最高权限
    allows: [
      { resources: ['/admin/reserve', '/admin/sign', '/admin/set'], permissions: ['get'] },
    ]
  }
];

校检

这里是结合express做校检...结果发现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/ 后面为 /符号认定也为过
      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: '用户未授权访问',
      //   };
      //   return res.status(401).send(err.message);
      // }
      next();
    };
  }

有点要说明的是express.Router支持导出一个Router模块 再在app.use使用,但是如果你这样使用 app.use('/admin/user',auth(), userRoute); 那么是在auth这个函数是获取不到 req.route 这个属性的。 因为acl对访问权限做的是强匹配,所以需要有一定的容错

登录的权限分配

result为数据库查询出来的用户信息,或者后台api返给的用户信息,这里的switch可以使用配置文件的形式,因为我这边本次项目只有三个权限,所以就在这里简单写了一下。

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渲染的时候是不会得出最终结果的,因为pug是同步的,那么我如何控制当前页面或者说当前页面的按钮用户是否有权限展示出来, 这里通用的做法有

  1. 用户在登录的时候有一个路由表和组件表 然后在渲染的时候 根据这个表去渲染

  2. 在需要权限控制的地方,使用函数来判断用户是否有权限访问

我这里采用的是结局方案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; // 目前数组第一个为单纯的get路由
    isFind = currentPath.includes(path);

    if (isFind) {
      // 如果找到包含该路径 并且method也对应得上 那么则通过
      if (i.permissions.includes(method)) {
        break;
      }

      // 如果找到该路径 但是method对应不上 则继续找.
      continue;
    }
  }

  return isFind;
};

上述代码页比较简单, 去遍历acl_conf,查找用户是否有当前页面的或者按钮的权限 因为acl_conf在加载的时候就已经被写入内存了,所以性能消耗不会特别大。比如下面的例子。

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 拒绝

结尾

依靠acl这个组件可以快速打造一个用户的权限管理模块。 但是还有个问题 也急速那个app.locals.hasRole函数, 如果你使用removeAllow动态改变了用户的权限表,那么hasRole函数就很麻烦了。 所以在这种情况下 有以下几个解决方案

  1. 从acl源码入手

  2. 每次渲染的时候就把数据准备好

const hasBtn1Role = hasRole(user.role, '/xxx','get');
res.render('a.pug',{hasBtn1Role})

上面是我整理给大家的,希望今后会对大家有帮助。

相关文章:

Angular中使用better-scroll插件的方法_AngularJS

Angularjs实现控制器之间通信方式实例总结

JavaScript代码实现txt文件的上传预览功能

相关专题

更多
php源码安装教程大全
php源码安装教程大全

本专题整合了php源码安装教程,阅读专题下面的文章了解更多详细内容。

61

2025.12.31

php网站源码教程大全
php网站源码教程大全

本专题整合了php网站源码相关教程,阅读专题下面的文章了解更多详细内容。

41

2025.12.31

视频文件格式
视频文件格式

本专题整合了视频文件格式相关内容,阅读专题下面的文章了解更多详细内容。

32

2025.12.31

不受国内限制的浏览器大全
不受国内限制的浏览器大全

想找真正自由、无限制的上网体验?本合集精选2025年最开放、隐私强、访问无阻的浏览器App,涵盖Tor、Brave、Via、X浏览器、Mullvad等高自由度工具。支持自定义搜索引擎、广告拦截、隐身模式及全球网站无障碍访问,部分更具备防追踪、去谷歌化、双内核切换等高级功能。无论日常浏览、隐私保护还是突破地域限制,总有一款适合你!

41

2025.12.31

出现404解决方法大全
出现404解决方法大全

本专题整合了404错误解决方法大全,阅读专题下面的文章了解更多详细内容。

198

2025.12.31

html5怎么播放视频
html5怎么播放视频

想让网页流畅播放视频?本合集详解HTML5视频播放核心方法!涵盖<video>标签基础用法、多格式兼容(MP4/WebM/OGV)、自定义播放控件、响应式适配及常见浏览器兼容问题解决方案。无需插件,纯前端实现高清视频嵌入,助你快速打造现代化网页视频体验。

9

2025.12.31

关闭win10系统自动更新教程大全
关闭win10系统自动更新教程大全

本专题整合了关闭win10系统自动更新教程大全,阅读专题下面的文章了解更多详细内容。

8

2025.12.31

阻止电脑自动安装软件教程
阻止电脑自动安装软件教程

本专题整合了阻止电脑自动安装软件教程,阅读专题下面的文章了解更多详细教程。

3

2025.12.31

html5怎么使用
html5怎么使用

想快速上手HTML5开发?本合集为你整理最实用的HTML5使用指南!涵盖HTML5基础语法、主流框架(如Bootstrap、Vue、React)集成方法,以及无需安装、直接在线编辑运行的平台推荐(如CodePen、JSFiddle)。无论你是新手还是进阶开发者,都能轻松掌握HTML5网页制作、响应式布局与交互功能开发,零配置开启高效前端编程之旅!

2

2025.12.31

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
React 教程
React 教程

共58课时 | 3.2万人学习

TypeScript 教程
TypeScript 教程

共19课时 | 1.9万人学习

Bootstrap 5教程
Bootstrap 5教程

共46课时 | 2.7万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号