nodejs acl的用户权限管理详解

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

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

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

功能列表:

addUserRoles //给某用户添加角色

removeUserRoles //移除某用户角色

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

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

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

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

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

removeRole //移除某角色

removeResource //移除某资源

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

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

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

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

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

whatResources //查询某角色有哪些资源

middleware //middleware for express

backend //指定方式(mongo/redis…)

ACL名词及其主要方法

roles 角色

removeRole

addRoleParents

allow

removeAllow

resources 资源

whatResources

removeResource

permissions 权限

users 用户

allowedPermissions

isAllowed

addUserRoles

removeUserRoles

userRoles

roleUsers

hasRole

areAnyRolesAllowed

使用方法

建立起配置文件

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

需要控制的地方使用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] === 'https://www.jb51.net/') { 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是同步的,那么我如何控制当前页面或者说当前页面的按钮用户是否有权限展示出来, 这里通用的做法有

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

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

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/pxsgw.html