@anishpras/rbac: 角色和属性基于访问控制
用于JavaScript/TypeScript应用的快速,灵活和可生产的角色访问控制(RBAC)系统.
特征
- 🚀 快速高效: 以 LRU 缓存方式优化速度
- 🔒 类型安全: 完整类型脚本支持
- 🧩 弹性: 定义自定义角色、资源和权限
- 🔄 角色等级: 支持角色继承,进行强力循环检测
- 🛠️ 中间软件支持: 准备使用Express.js和其他框架
- 📝 流利的 API: 配置的直观构建器模式
- 📊 运行时间更新: 不重新启动而修改权限
- 🧪 严格模式: 对未识别角色/资源的可选投放
- 📈 可缩放: 为大规模应用设计
安装
npm install @anishpras/rbac
# or
yarn add @anishpras/rbac
# or
pnpm add @anishpras/rbac
快速启动
import { RBACManager, RBACBuilder } from '@anishpras/rbac';
// Create a configuration using the builder
const config = new RBACBuilder()
.role('ADMIN', 'Administrator with full access')
.grantFullAccess('Products')
.grantFullAccess('News')
.grantFullAccess('Bookings')
.done()
.role('EDITOR', 'Editor with limited access')
.forResource('Products').grantAll().and()
.forResource('News').grantAll().and()
.forResource('Bookings').grantReadOnly().done()
.setDefaultRole('EDITOR')
.build();
// Create the RBAC manager
const rbac = new RBACManager(config, {
cache: {
enabled: true,
maxSize: 1000,
ttl: 60 * 1000 // 1 minute
},
strict: false, // Avoid runtime errors in production
logger: {
debug: (msg) => console.debug(`[RBAC] ${msg}`),
info: (msg) => console.info(`[RBAC] ${msg}`),
warn: (msg) => console.warn(`[RBAC] ${msg}`),
error: (msg) => console.error(`[RBAC] ${msg}`)
}
});
// Check permissions
const user = {
id: 1,
roles: ['EDITOR']
};
// Check if a user can create a product
if (rbac.userCan(user, 'Products', 'CREATE')) {
// User can create products
}
// Check if a user can update a booking
if (rbac.userCan(user, 'Bookings', 'UPDATE')) {
// User cannot update bookings
}
Express.js Midddleware 示例
import express from 'express';
import { RBACManager } from '@anishpras/rbac';
const app = express();
const rbac = new RBACManager(config);
// Middleware to protect routes
app.get(
'/api/products',
rbac.middleware({
getUserRoles: (req) => req.user.roles,
resource: 'Products',
permission: 'READ',
onDenied: (req, res) => {
res.status(403).json({ error: 'Access denied' });
}
}),
(req, res) => {
// Handle the request
}
);
// Dynamic permission based on HTTP method
app.all(
'/api/bookings/:id',
rbac.middleware({
getUserRoles: (req) => req.user.roles,
resource: 'Bookings',
permission: (req) => {
// Map HTTP method to permission
switch (req.method) {
case 'GET': return 'READ';
case 'POST': return 'CREATE';
case 'PUT': case 'PATCH': return 'UPDATE';
case 'DELETE': return 'DELETE';
default: return 'READ';
}
},
onDenied: (req, res) => {
res.status(403).json({
error: 'Access denied',
message: `You don't have permission to ${req.method} bookings`
});
}
}),
(req, res) => {
// Handle the request
}
);
理解角色等级( 继承)
角色等级特征允许角色从其他角色继承权限. 这是图书馆最强大但有时令人困惑的方面之一.
// Define role hierarchy
rbac.setRoleHierarchy({
'EDITOR': ['ADMIN'], // EDITOR inherits all permissions from ADMIN
'VIEWER': ['EDITOR'] // VIEWER inherits all permissions from EDITOR
});
关于角色等级的重要澄清数字 :
在角色等级配置中:
- 这个
key这是 儿童角色 (继承权限的) - 这个
array values这是 父角色 (继承者)
这意味着:
'EDITOR': ['ADMIN']表示EDITOR继承了行政主管的权限,而不是相反'VIEWER': ['EDITOR']表示VIEWER从EDITOR继承(并转自行政主管)
像这样想:
'CHILD_ROLE': ['PARENT_ROLE_1', 'PARENT_ROLE_2']
让我们看看一个更完整的例子,来说明角色等级如何发挥作用:
// Define role hierarchy with more complex relationships
rbac.setRoleHierarchy({
// Store roles inherit from more general roles
'STORE_MANAGER': ['ADMIN'], // Store Manager inherits from Admin
'STORE_CLERK': ['STORE_MANAGER'], // Store Clerk inherits from Store Manager
// Content roles also inherit
'CONTENT_EDITOR': ['ADMIN'], // Content Editor inherits from Admin
'CONTENT_VIEWER': ['CONTENT_EDITOR'], // Content Viewer inherits from Content Editor
// Special case: dual inheritance
'SUPERVISOR': ['STORE_MANAGER', 'CONTENT_EDITOR'] // Inherits from both roles
});
// Let's test some permissions
console.log(rbac.can('STORE_CLERK', 'Products', 'READ')); // true if STORE_MANAGER has this permission
console.log(rbac.can('SUPERVISOR', 'Content', 'PUBLISH')); // true if either parent role has this permission
库会自动处理过渡性继承,并检测循环引用来防止无限循环.
动态权限更新
您可以在运行时修改权限而不重新启动您的应用程序 :
// Add a new role
rbac.addRole('MANAGER', {
description: 'Manager role',
permissions: {
'Products': ['READ', 'UPDATE'],
'Bookings': ['READ', 'UPDATE', 'CREATE']
}
});
// Grant new permissions
rbac.grant('EDITOR', 'Reports', ['READ']);
// Revoke permissions
rbac.revoke('EDITOR', 'Bookings', ['DELETE']);
// Revoke all permissions on a resource
rbac.revoke('EDITOR', 'Bookings');
// Remove a role entirely
rbac.removeRole('GUEST');
// Update the entire configuration
rbac.updateConfig(newConfig);
记住在权限更改后清除缓存( 内置方法如 grant() 财务报告和审定财务报表 revoke() 自动处理此选项 :
// Manually clear the cache when needed
rbac.clearCache();
政策评价
您可直接评价相关政策:
const policyResult = rbac.evaluatePolicy({
role: 'EDITOR',
resource: 'Products',
permission: 'UPDATE'
});
console.log(policyResult.allowed); // boolean
console.log(policyResult.reason); // explanation string
查询可用的权限和资源
// Get all permissions a role has on a resource
const permissions = rbac.getPermissions('EDITOR', 'Products');
// Returns: ['CREATE', 'READ', 'UPDATE', 'DELETE']
// Get all resources a role has access to
const resources = rbac.getResources('ADMIN');
// Returns: ['Products', 'News', 'Bookings', ...]
// Get all roles in the system
const roles = rbac.getRoles();
// Returns: ['ADMIN', 'EDITOR', 'VIEWER', ...]
// Get cache statistics
const cacheStats = rbac.getCacheStats();
// Returns: { enabled: true, size: 42 }
最佳做法
1. 作用、资源和权限使用常量
定义常数,以防止打字并确保一致性:
// Define constants
const ROLES = {
ADMIN: 'ADMIN',
EDITOR: 'EDITOR',
VIEWER: 'VIEWER'
} as const;
const RESOURCES = {
PRODUCTS: 'Products',
USERS: 'Users',
ORDERS: 'Orders'
} as const;
const PERMISSIONS = {
CREATE: 'CREATE',
READ: 'READ',
UPDATE: 'UPDATE',
DELETE: 'DELETE'
} as const;
// Use constants in your code
rbac.grant(ROLES.EDITOR, RESOURCES.PRODUCTS, [PERMISSIONS.READ, PERMISSIONS.UPDATE]);
2. 非限制性生产方式
设定 strict: false 在生产中防止为未定义的角色或资源扔出错误。 如果一个角色被引用而不存在,这可以防止服务中断.
const rbac = new RBACManager(config, {
strict: process.env.NODE_ENV === 'development'
});
3. 启用缓存
生产中总是使用缓冲来提高性能:
const rbac = new RBACManager(config, {
cache: {
enabled: true,
maxSize: 1000, // Limit cache size to prevent memory issues
ttl: 5 * 60 * 1000 // Cache TTL of 5 minutes
}
});
4. 适当设置角色等级
记住在等级对象中:
- 关键是孩子的角色(继承权限的)
- 数组值为父角色( 从中继承)
// CORRECT:
rbac.setRoleHierarchy({
'EDITOR': ['ADMIN'], // EDITOR inherits from ADMIN
});
// INCORRECT (would mean ADMIN inherits from EDITOR):
rbac.setRoleHierarchy({
'ADMIN': ['EDITOR']
});
5. 使用自定义记录器
配置自定义日志以整合您的应用程序的日志系统 :
const rbac = new RBACManager(config, {
logger: {
debug: (msg) => myLogger.debug(`[RBAC] ${msg}`),
info: (msg) => myLogger.info(`[RBAC] ${msg}`),
warn: (msg) => myLogger.warn(`[RBAC] ${msg}`),
error: (msg) => myLogger.error(`[RBAC] ${msg}`)
}
});
6. 落实资源所有权
关于多租户系统,结合非洲区域局和资源所有权检查:
// Middleware to check both permissions and ownership
const checkPermissionAndOwnership = (req, res, next) => {
const resourceId = req.params.id;
const userId = req.user.id;
// First check RBAC permissions
if (!rbac.userCan(req.user, 'Orders', 'UPDATE')) {
return res.status(403).json({ error: 'Permission denied' });
}
// Then check ownership
orderService.getOrderById(resourceId)
.then(order => {
if (order.userId !== userId) {
return res.status(403).json({ error: 'Not your order' });
}
next();
});
};
安全特性
此软件包包含安全性重点功能,以保护您的应用程序的许可系统:
-
输入验证:所有角色,资源和许可输入都经过验证,以防止注射攻击和操纵.
-
循环参考检测:在角色等级中自动检测并预防循环引用.
-
默认拒绝:当出错或角色/许可未定义时,系统总是默认拒绝访问.
-
深克隆:所有配置对象被深克隆来防止外部突变攻击.
-
保护缓存密钥:缓存系统使用已消毒的密钥来防止缓存中毒.
-
安全中间软件:"快递"中间软件的设计是为了安全地处理出错,总是默认访问拒绝.
-
审计日志:为关键许可更改和访问尝试而构建的审计记录.
-
类型安全: TypeScript类型执行适当的结构并预防常见的错误.
-
种族条件保护: 特殊处理,在许可更新期间防止种族条件.
-
安全错误处理:错误消息的设计是为了避免泄露敏感信息.
高级示例
对于更高级的用法示例,请检查 examples 存储器中的目录 :
product-shop.ts:具有标准作用的基本电子商务实例express-integration.ts: 与 Express.js 中间软件的示例集成advanced-example.ts: 具有综合权限的复杂角色等级
API 参考
非洲区域局经理
管理RBAC功能的主要类.
// Create a new instance
const rbac = new RBACManager(config, options);
// Check if a role has permission
rbac.can(role, resource, permission);
// Check if a user has permission
rbac.userCan(user, resource, permission);
// Set role hierarchy
rbac.setRoleHierarchy(hierarchy);
// Update configuration
rbac.updateConfig(config);
// Add a new role
rbac.addRole(role, definition);
// Remove a role
rbac.removeRole(role);
// Grant permissions
rbac.grant(role, resource, permission);
// Revoke permissions
rbac.revoke(role, resource, permission);
// Evaluate a policy
rbac.evaluatePolicy(policy);
// Get permissions for a role on a resource
rbac.getPermissions(role, resource);
// Get all resources a role has access to
rbac.getResources(role);
// Get all roles
rbac.getRoles();
// Get the complete configuration
rbac.getConfig();
// Clear the permission cache
rbac.clearCache();
// Get cache statistics
rbac.getCacheStats();
// Create middleware
rbac.middleware(options);
非洲区域局
用于构建RBAC配置的流利API.
// Create a new builder
const builder = new RBACBuilder();
// Define roles and permissions
builder
.role('ADMIN')
.grantFullAccess('Products')
.done()
.role('EDITOR')
.forResource('Products').grant('READ', 'UPDATE').and()
.forResource('News').grantAll().done()
.setDefaultRole('EDITOR');
// Build the configuration
const config = builder.build();
建设与发展
项目建设
该项目提供了开发和生产建设的备选方案:
# Development build (with source maps and comments)
npm run build
# Production build (minified with source maps)
npm run build:prod
缩小
生产构造用特尔泽自动将JavaScript输出分解,优化如下:
- 代码压缩( 删除白空间, 缩短可变名称)
- 取消死亡代码
- 为较小的文件大小管理可变名称
- 保留许可证/版权评论
- 调试的 sourcemap 生成
这导致文件大小明显较小,同时保持了完整的功能.
许可证
麻省理工学院