【问题标题】:Strategy for Modeling RBAC with NoSQL Document Store使用 NoSQL 文档存储对 RBAC 进行建模的策略
【发布时间】:2012-03-17 05:00:49
【问题描述】:

我正准备在我的应用程序中实现 role based access control 的精简版本,我正在考虑如何/在我的 document store 中建模,这恰好是 mongodb 与 mongoose.js 作为我的“便利库” .但是这个问题应该适用于任何文档存储。

考虑到重复与性能等竞争因素,在使用文档存储时,在使用嵌入式对象和引用之间做出决定似乎很常见。我试图使 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;
    }
  }
}

【问题讨论】:

    标签: mongodb mongoose nosql


    【解决方案1】:

    我最近使用 mongoosejs 来满足 Drywall.js 的用户/角色/权限需求 - 实际权限是基于键/值的。它们可以按组共享,也可以在管理员级别上精细地覆盖。

    虽然它不完全是 RBAC,但我希望回顾另一种方法可以帮助您更接近实现目标。

    项目概述:

    Mongoose 架构:

    具体看:

    • /schema/User.js
    • /schema/Admin.js
    • /schema/AdminGroup.js
    • /schema/Account.js

    我很想看看你的想法。

    【讨论】:

      【解决方案2】:

      您的设计几乎完全取决于应用程序的行为。根据您在此处提供的信息,我建议将数据保存在键/值中,而不是保存在数据库中——CRUD 操作不会改变,因此没有理由将其放入数据库中。 “资源”是您已经内置到代码中的类,因此您也不需要在数据库中复制它。

      【讨论】:

      • 但是如果我想为管理员提供一种方法来更改角色内的权限会发生什么。所以看看我的例子,用户希望允许“作家”能够对用户进行读取访问。他们必须有权访问代码本身。这就是为什么我想存储这些。因此,在这种情况下,您的界面允许他们选择复选框等,并且该应用程序的角色现在已更改。抱歉,我没有说清楚,我会编辑我的帖子。
      • 不,没关系,我明白你想要做什么。您在 EDIT 中输入的内容可以正常工作。
      猜你喜欢
      • 2014-07-31
      • 2015-07-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-01-18
      • 1970-01-01
      • 2020-10-17
      • 2018-12-08
      相关资源
      最近更新 更多