我已经准备好在我的应用程序中实现精简版role based access control了,我正在考虑如何/在我的document store中建模,而mongod是mongod,mongoose.js “便利库”。但是这个问题应该适用于任何文档存储。
在使用文档存储时,使用嵌入对象与refs之间的决定似乎很常见,因为复制与性能的竞争因素有所不同。我试图保持RBAC尽可能简单,不要在嵌套的Collections / Ref ID上过于疯狂,这意味着大量的循环,而不是使用mongoose的填充等。
问题:
我已经倾向于拥有用户,权限和角色的集合;但是为操作和资源建模是否有意义,或者只是使用键/值来实现这些?
请参阅下面的代码示例或 jsfiddle ,这有助于解决问题。请注意,这并不是我想要实现的方式,而只是一种检查关系的方法!
/*
Imagine this being used in a CMS ;)
User: have a role property (e.g. role:"admin" or role:"writer")
Operation: Create,Read,Update,Delete,etc.
Resource: Page,Post,User, etc.
* For simplicity, we can represent operations and resource with simple strings.
Permission: A permission is an allowable "Operation" on a "Resource"
Role: A Role is just an abstraction of a set of possible "Permissions"
*/
// I could see this as a Permission model in mongo
var adminPerms = {
create: ['pages','posts', 'users'],
update: ['posts','pages','users'],
update_others: ['posts','pages'],
delete: ['posts','pages','users'],
read:['pages','posts','users']
};
// I could see this as a Role model in mongo
var admin = {
perms: adminPerms
};
var writerPerms = {
create: ['pages','posts'],
update: ['pages','posts'],
update_others: [],
delete: [],
read:['pages','posts']
};
var writer = {
perms: writerPerms
};
// Now we can just see if that user's perms has the operation on resource defined
function hasPerms(user, operation, resource) {
var i, len, op;
if(!user || !user.role || !operation || !resource) return false;
if(typeof rolemap[user.role] !== 'undefined' &&
typeof rolemap[user.role]['perms'] !== 'undefined' &&
typeof rolemap[user.role]['perms'][operation] !== 'undefined') {
op = rolemap[user.role]['perms'][operation];
for(i=0, len=op.length; i<len; i++) {
if(op[i] === resource) {
return true;
}
}
}
return false;
}
var rolemap = {"admin":admin, "writer":writer}
var user_admin = {name:'Rob Levin', role:'admin'}
var user_jack = {name:'Jack Black', role:'writer'}
hasPerms(user_jack, 'create', 'users')
// false
hasPerms(user_admin, 'create', 'users')
// true
hasPerms(user_admin, 'update_others', 'posts')
// true
hasPerms(user_jack, 'update_others', 'posts')
// false
编辑:假设角色必须基于每个应用程序进行编辑,因此我可能希望允许管理员用户控制访问权限;这就是我想使用数据库的原因。
关于在应用程序中执行所有操作,考虑到持久性和可能更改的要求,这将无法工作。但是,在这方面的一个妥协是我可以只收集角色:
db.role.find({name:'writer'}).pretty()
{
"_id" : ObjectId("4f4c2a510785b51c7b11bc45"),
"name" : "writer",
"perms" : {
"create" : [
"posts",
"pages"
],
"update" : [
"posts",
"pages"
],
"update_others" : [ ],
"delete" : [ ],
"read" : [
"posts",
"pages"
]
}
}
而且我可以像删除一样进行更改,如下所示(假设我已经有一个在调用时从mongo检索到的角色对象的引用):
function removePerm(role, op, resource) {
if(!role || !role.perms || !role.perms[op]) {
console.log("Something not defined!");
return false;
}
var perm = role.perms[op];
for(var i=0, len=perm.length; i<len; i++) {
if(perm[i] === resource) {
perm.splice(i,1);
break;
}
}
}
答案 0 :(得分:3)
我最近使用了mongoosejs,其中包含我对Drywall.js的用户/角色/权限 - 实际权限是基于键/值的。它们可以由组共享,也可以在管理员级别上进行细化。
虽然它不完全是RBAC我希望审查另一种方法可以帮助您更接近实现目标。
项目概述:
Mongoose Schemas:
具体看看:
我很想知道你的想法。
答案 1 :(得分:1)
您的设计几乎完全取决于您的应用程序的行为。根据您在此处提供的信息,我建议将数据保存在键/值中,而不是数据库中 - CRUD操作不会改变,因此没有理由将其放在数据库中。 “资源”是您已经在代码中构建的类,因此您无需在数据库中复制它。