在现代的 Web 应用中,权限管理是必不可少的一部分。但是在实现权限管理时,我们需要处理各种各样的问题,例如用户与角色、角色与权限之间的关系,如何在前端和后端保持同步,如何实现细粒度的权限控制,以及如何应对变化和扩展等等。这些问题对于开发者来说是非常繁琐且难以解决的。
在这个问题上,sudosu- 来解救我们!sudosu- 是一款轻量级、简单易用的权限管理框架,提供了强大的 ACL(访问控制列表)功能和易于扩展的架构。它可以帮助你更快捷、更可靠地实现权限管理,并帮你应对变化和扩展。
一、快速入门
首先让我们来看一个最简单的入门示例。假设我们有一个用户表和一个文档表,我们想要限制用户只能查看、修改和删除自己的文档。我们可以用 sudosu- 来实现这个功能,示例代码如下:
const sudosu = require('sudosu');
// 首先定义一个 ACL 对象
const acl = sudosu.createAcl();
// 添加角色和权限
acl.allow('user', 'document', ['view', 'edit', 'delete']);
// 下面是一个用户查看、修改和删除文档的例子
const user = { id: 123 };
const document = { id: 456, owner: 123 };
// 用户查看文档
if (acl.isAllowed(user.id, 'document', 'view')) {
console.log('用户可以查看文档');
} else {
console.log('用户无权查看文档');
}
// 用户修改文档
if (acl.isAllowed(user.id, 'document', 'edit', { owner: document.owner })) {
console.log('用户可以修改文档');
} else {
console.log('用户无权修改文档');
}
// 用户删除文档
if (acl.isAllowed(user.id, 'document', 'delete', { owner: document.owner })) {
console.log('用户可以删除文档');
} else {
console.log('用户无权删除文档');
}
这个示例中,我们定义了一个 ACL 对象,并为角色 user 添加了权限 document:view、document:edit 和 document:delete。然后我们模拟了一个用户查看、修改和删除文档的场景,使用 acl.isAllowed() 方法来检查用户是否有权执行相应的操作。
二、ACL 与角色
在 sudosu- 中,我们可以通过 Allow 和 Deny 方式为角色设置权限。例如,我们可以为管理员和普通用户设置不同的访问权限:
const acl = sudosu.createAcl();
// 添加管理员角色和权限
acl.allow('admin', 'users', ['view', 'edit', 'delete']);
acl.allow('admin', 'documents', ['view', 'edit', 'delete']);
// 添加普通用户角色和权限
acl.allow('user', 'users', ['view', 'edit profile']);
acl.allow('user', 'documents', ['view', 'create own', 'edit own', 'delete own']);
// 检查用户是否有权查看某个文档
if (acl.isAllowed(user.id, 'documents', 'view', { owner: document.owner })) {
console.log('用户可以查看该文档');
} else {
console.log('用户无权查看该文档');
}
// 检查用户是否有权编辑某个文档
if (acl.isAllowed(user.id, 'documents', 'edit own', { owner: document.owner })) {
console.log('用户可以编辑该文档');
} else {
console.log('用户无权编辑该文档');
}
在上面的示例中,我们为管理员和普通用户定义了不同的权限。管理员可以访问和编辑用户和文档,而普通用户只能编辑自己的文档和资料。我们使用 acl.isAllowed() 方法来检查用户是否有权执行相应的操作。注意,我们使用了 `edit own` 来限制用户只能编辑自己的文档。
三、ACL 与资源
在 sudosu- 中,权限控制是针对资源的,资源可以是一个页面、一个文件、一个数据集合等等。在实现权限控制时,我们需要明确资源的概念,以便对其进行 ACL 配置。例如,我们可以为用户、文章和评论设置不同的权限:
const acl = sudosu.createAcl();
// 添加用户角色和权限
acl.allow('user', 'comments', ['view own', 'edit own', 'delete own']);
acl.allow('user', 'articles', ['view', 'edit own', 'delete own', 'comment']);
// 添加管理员角色和权限
acl.allow('admin', 'comments', ['view', 'edit any', 'delete any']);
acl.allow('admin', 'articles', ['view any', 'edit any', 'delete any', 'comment']);
// 定义两个示例用户
const user1 = { id: '123', is_admin: false };
const user2 = { id: '456', is_admin: true };
// 检查用户 1 是否有权删除自己的评论
if (acl.isAllowed(user1.id, 'comments', 'delete own', { user_id: user1.id })) {
console.log('用户 1 可以删除自己的评论');
} else {
console.log('用户 1 无权删除自己的评论');
}
// 检查用户 1 是否有权编辑文章
if (acl.isAllowed(user1.id, 'articles', 'edit', { author_id: user1.id })) {
console.log('用户 1 可以编辑自己的文章');
} else {
console.log('用户 1 无权编辑自己的文章');
}
// 检查用户 2 是否有权删除评论
if (acl.isAllowed(user2.id, 'comments', 'delete any')) {
console.log('用户 2 可以删除任何评论');
} else {
console.log('用户 2 无权删除任何评论');
}
在这个示例中,我们定义了两个角色(user 和 admin)和两个资源(comments 和 articles),并为它们设置了不同的权限。我们使用 `view own` 和 `delete own` 来限制用户只能查看和删除自己的评论,而使用 `view any`、`edit any` 等来允许管理员查看和编辑任何资源。
四、构建自定义验证函数
sudosu- 为我们提供了许多常用的验证函数,但如果我们需要更复杂的验证逻辑,可以通过构建自定义函数来实现。例如,我们可以针对用户的角色、等级、是否关注等因素进行验证。
const acl = sudosu.createAcl();
const db = require('./database');
// 定义一个自定义验证函数
function checkFollower(user, author, cb) {
db.isFollowing(user.id, author.id, (err, isFollowing) => {
if (err) return cb(err);
if (isFollowing) {
cb(null, true); // 验证通过
} else {
cb(null, false); // 验证未通过
}
});
}
// 添加一个权限规则
acl.allow('user', 'articles', 'edit', checkFollower);
// 检查用户是否能够编辑文章
if (acl.isAllowed(user.id, 'articles', 'edit', { author_id: author.id })) {
console.log('用户可以编辑文章');
} else {
console.log('用户无权编辑文章');
}
在这个示例中,我们定义了一个自定义验证函数 checkFollower,它会在用户编辑文章时检查该用户是否关注了作者。我们使用 acl.allow() 方法来为角色添加权限,其中第四个参数是一个自定义验证函数。然后我们使用 acl.isAllowed() 方法来检查用户是否有权执行相应的操作。
五、结语
在上面的几个例子中,我们演示了如何使用 sudosu- 实现简单、复杂的权限管理。sudosu- 提供了一套强大的 ACL 功能和易于扩展的架构,可以帮助我们更快、更可靠地实现权限管理。
如果你想了解更多关于 sudosu- 的使用方法和内部原理,请参考官方文档。