【问题标题】:Advanced permissions with couchdbcouchdb 的高级权限
【发布时间】:2014-09-16 04:14:29
【问题描述】:

我们有一个 couchapp 应用程序,它有多个用户和一个复杂的权限系统。 我们的模型有两种:Foo 和 bar。

用户拥有自己的 Foo 和 Bar 的管理员权限,并且可以被授予查看、更改和删除其他人的 Foo 和 Bar 的权限。

例子:

用户 Sabrina 有这些模型:

Foo {
  _id: 1
}
Foo {
  _id: 2
}
Bar {
  _id:1
}
Bar {
  _id:2
}

当然,真正的模型是更大的文档。

她想授予 Giulia 对她的 Foos 的读取权限,以及对她的第一个 bar 的读写权限。她还希望 Giulia 不能看到她的第二个酒吧。

我们如何在 couchdb 中为这种权限建模?

这是我们正在使用的解决方案,但它似乎很复杂,我们想知道是否有更简单的解决方案:

我们有多种角色可供选择: {username}:admin: 可以读取、写入、删除与用户相关的每个数据库上的所有内容 {username}:foos:read:可以读取foos数据库中与用户相关的每一个文档 {username}:foos:write:可以写入foos数据库中与用户相关的每一个文档 {username}:{bar}:read:可以读取用户相关的Bar数据库 {username}:{bar}:write: 可以写用户相关的Bar数据库

当 Sabrina 注册到应用程序时,我们会创建一个新的 sabrina-foos 数据库,并将角色 sabrina:admin 分配给用户 Sabrina。

sabrina-foos 数据库是使用_security 文档创建的,该文档授予对角色sabrina:adminsabrina:foos:readsabrina:foos:write 的访问权限。

sabrina-foos 数据库是使用验证功能创建的,该功能允许对角色sabrina:adminsabrina:foos:write 进行写访问。

当 Sabrina 决定让 Giulia 看到她的 foos 时,我们赋予 Giulia 角色 sabrina:foos:read

当 Sabrina 创建一个名为“Bar 1”的新 Bar 时,我们会创建一个新的 sabrina-bar_1 数据库。

sabrina-bar_1 数据库是使用 _security 文档创建的,该文档授予对角色 sabrina:adminsabrina:bar_1:readsabrina:bar_1:write 的访问权限

sabrina-bar_1 数据库是使用验证功能创建的,该功能允许对角色sabrina:adminsabrina:bar_1:write 进行写访问。

当然,作为一个 CouchApp,数据库的创建和用户模型的编辑由 Node Process 处理。

【问题讨论】:

  • 您是否考虑过将授权完全外部化?以 XACML 为例。
  • @DavidBrossard XACML 看起来不错。感谢分享。

标签: permissions authorization couchdb couchapp


【解决方案1】:

你的设计很好。从您的问题来看,您似乎想要文档级别的身份验证。 couchdb 不对单个文档提供任何保护,因此 剩下的唯一选择是按数据库对文档进行分区并对其设置读写权限。

有两种选择。最简单的是使用 rcouch's validate docs on read。我也不是 当然,但我认为在 couch db 2.0 中所有 rouch 的功能都已合并,因此如果您愿意稍等片刻,您可以使用 couchdb 2.0(它现在应该随时可用!)。

另一种方法是在_users 数据库中执行您正在执行的操作。在_users 数据库中,您可以 创建用户并使用_sessions api 对其进行身份验证。所以这就是它的工作原理。

  1. 您创建的每个新用户都将进入_users 数据库。
  2. 在用户文档中,您可以存储允许用户查看哪些文档的列表,或者您是否可以查看 担心单个用户文档会变得太大,然后只存储一个指向可能包含 用户可以查看的实际列表。
  3. 首先使用_sessions api 对用户进行身份验证,然后获取用户被授权的文档列表 阅读或编辑。
  4. 最终获取这些文档并show 将其提供给用户。

这种方法的优点是您将需要最少 2 个,最多 3 个 http 查询。一个进行身份验证并获取指向列表的指针。其次是获取要获取的文档的实际列表。第三,获取这些文件。作为回报,您的架构将大大简化。

_users 数据库的一个非常酷的属性是您可以在配置中增加身份验证缓存大小以将_user 对象保存在内存中,这样访问时间会非常快。

如果我有一万个文档但我只能检索其中一个怎么办?函数会被调用一万次吗?

我目前没有安装 rcouch,但是有一个简单的方法可以通过记录来测试它:-

function(doc, userCtx) {
    log("function called");
    if ((typeof doc.name !== 'undefined') && (doc.name != userCtx.name)) {
        throw({unauthorized: userCtx.name + ' cannnot read ' + doc._id});
    }
}

日志功能将在日志文件中打印一条日志消息,并且还会在 couchdb 正在运行的控制台上打印,以便您自己查看更新功能被调用了多少次。如果你能分享结果会很好:)

【讨论】:

  • Rcouch 可能是要走的路。谢谢
  • 我想知道结果是否以某种方式缓存。如果我有一万个文档,但我只能检索其中一个怎么办?函数会被调用一万次吗?
  • 周末我试试
猜你喜欢
  • 1970-01-01
  • 2014-02-26
  • 2014-12-20
  • 1970-01-01
  • 2021-06-22
  • 1970-01-01
  • 1970-01-01
  • 2016-04-13
  • 2016-08-22
相关资源
最近更新 更多