CouchDb 使用列表读取身份验证

Posted

技术标签:

【中文标题】CouchDb 使用列表读取身份验证【英文标题】:CouchDb read authentication using lists 【发布时间】:2011-04-01 16:29:29 【问题描述】:

我正在考虑在 CouchDB 中移植一个网站,它看起来很有趣。

然而,一个大问题是 CouchDB 似乎不支持读认证;所有读者都可以访问数据库中的所有文档。

建议elsewhere 为不同的读者组使用不同的数据库或在另一个(中间)层中实现读者身份验证,对于这个访问由复杂的每个文档 ACL 确定的项目来说,这两种方法都不是一个选项.

我正在考虑在 lists 中实现身份验证,并将对 CouchDb 的所有访问权限限制在这些列表中。这个限制可以通过 Apache 中用作反向代理的简单 mod_rewrite 子句来强制执行。列表将简单地获取行并根据文档的 ACL 检查 userCtx。比如:

function(head, req) 
  var row;
  while (row = getRow()) 
     if (row.value.ACL[req.userCtx.name])
       send(row.value);
     else
       throw(unauthorized : "You are not allowed to access this resource");

由于我没有使用 CouchDB 的经验,也没有在任何地方读到过这种方法,我想知道这种方法是否可行。

这是实现读取访问的一种方式,还是我出于错误目的滥用列表?我不应该期望 CouchDB 可以提供如此简单的解决方案吗?

【问题讨论】:

看看github.com/ermouth/covercouch——它实现了读取 ACL,保持原始 CouchDB REST API 不变。 【参考方案1】:

Apache mod_rewrite 是一个中间层,所以当你说中间层不是一个选项时,你并不清楚你的意思。

根据 couchdb 中的数据实施您的安全策略非常好。但是,代价是您有责任确保实施正确。它并不像听起来那么糟糕。请记住,人们已经使用 mysql Web 应用程序执行此操作已有很长时间了。

要记住的是,CouchDB 不支持文档级别的读取权限,因为跟踪这些权限是不切实际的,因为数据会在所有映射中编织并减少视图。例如,假设我们有一个投标系统。

有两个出价,我的和你的 我已获得 10 美元出价的读取权限,但由于中间件政策,我无法读取您的出价文件 但是,我发现了一个计算所有出价平均值的视图。平均价格为 7.50 美元。因此,我知道您出价 5 美元,我会将出价降低到 6 美元

换句话说,如果您包装 CouchDB API,您将至少需要将那些允许的查询列入白名单。请记住,虚拟主机和重写规则在 CouchDB 中运行,因此仅查看传入的查询可能还不够。

希望这能阐明为什么读取控制在数据库级别。

【讨论】:

谢谢。 “在 CouchDB 中运行的虚拟主机和重写规则”是什么意思? 您(或某人)能否更具体地说明 LISTS 是否是实现此目的的好方法? 嗨,托马斯。简短的回答:no。一般来说,列表不是执行安全策略的好方法,因为用户可以简单地查询 /_all_docs 并查看整个数据库! 只需使用 CouchDB 托管服务提供商,它会为您完成代理部分。在 Smileupps 上,您可以在需要时定义/重新定义/删除您想要的所有域。然后,您可以完全更改或删除您的 CouchDB 根访问域,并通过过滤重写 doc 规则将其他“公共”域链接到 ddoc.. 从而防止访问任何受限制的处理程序,如 _all_docs 和其他..【参考方案2】:

通常限制对某些视图的访问就足够了 - 这可以通过您建议的列表来完成(感谢您的想法)。对文档使用不可猜测的 ID,您已经对文档进行了某种访问控制。我会避免遍历行并检查那里的权限,但我认为这也不是什么大问题。

这里有些人提到列表的目的是改变格式 - 我不同意,因为即使是官方 CouchDB 指南也指出列表甚至可以生成 json 文档。

另一种方法是限制每个数据库的用户并使用选择性复制,这样一个数据库将只包含允许特定用户组访问的数据。请参阅couchdb read authentication 这实际上不是每个用户,但无论如何可能是您的选择。有关过滤复制的详细信息,请参阅http://wiki.apache.org/couchdb/Replication

编辑:我刚刚想出了一个好主意,通过性能更好的列表来强制执行每个文档的用户权限:

    您将用户名作为参数传递给视图并进行相应过滤。 在使用视图的列表中,检查给定参数用户名是否与实际用户相同。

据我所知,优点是 CouchDB 在内部使用缓存来处理视图。我不确定缓存如何与列表一起使用。此外,我认为在视图中迭代和过滤通常比在列表中更快。

【讨论】:

感谢您的回答。关于您编辑的想法,这似乎仅在有限的情况下有用,即不需要在用户名上进行排序或过滤,对吗? 不,你可以随心所欲地使用它,因为 CouchDB 允许对多个值进行排序。只需执行“emit([doc.user_id, doc.sort_value], doc)”之类的操作即可。 不错的答案。但请记住,用户可以获取 /_all_docs 并查看整个数据库!如果您有一个代理层,并且您确定它会阻止所有非内嵌的 URL,那么列表可以工作。但这很微妙。重写、显示/列出函数和视图都可能为数据打开后门。 只需使用 CouchDB 托管服务提供商,它会为您完成代理部分。在 Smileupps 上,您可以在需要时定义/重新定义/删除您想要的所有域。然后,您可以完全更改或删除您的 CouchDB 根访问域,并通过过滤重写文档规则将其他“公共”域链接到 ddoc【参考方案3】:

列表函数是在简单情况下强制执行读取 ACL 的合理方法,但这种方法有几个缺点。

首先,您需要在 CouchDB 前面有一些东西来阻止任何读取请求,它不会通过实现 ACL 的列表 fn 进行管道传输。 _all-docsreduce=true 的请求、文档的直接 GET——必须阻止所有人以及许多其他人。最简单的方法是使用 Apache 和正则表达式掩码。

第二,你必须明白你不能以简单的方式控制对附件的访问。尽管您可以阻止任何与您的/db/_design/ddoc/_list/list/view 模式不匹配的读取请求,但您无法构建有效的视图+列表对来提供对附件的访问控制。

绝对对于 CouchDB 1.5 及更早版本是不可能的——视图索引不能包含附件数据。这几乎在 CouchDB 1.6 中是不可能的,因为将 base64 编码的附件处理为 JSON 会占用 CPU 和 RAM。

第三,无论如何,这种方法是sloooooow。原因很简单——列表函数不是流。这意味着首先获取视图 fn 的整个响应并序列化,然后列表处理器再次对其进行反序列化,然后使用列表函数处理结果。然后,再次序列化。

【讨论】:

【参考方案4】:

我不确定使用 list 是限制对资源的访问的最佳选择,因为 list 是用于以特定格式(RSS、CSV、配置文件、html、... )。

您是否考虑过使用包含用户及其权限的文​​档?我找到了a post by Kore Nordmann,它解释了如何将经典的用户/组/权限从关系数据库转换为 CouchDB 模型:

根据其权限,用户只能访问一组已定义的视图。

CouchDB 提供验证功能,但它们仅在创建或更新文档时被调用。 O’Reilly book 声明“身份验证系统是可插拔的,因此您可以与现有服务集成,以使用 http 层、LDAP 集成或通过其他方式对 CouchDB 的用户进行身份验证”。但是由于您提到中间层不是一个选项,因此在向 CouchDB 添加更多身份验证支持之前,该列表可能是一个临时解决方案。

【讨论】:

谢谢。 Kore Nordmann 的帖子使用用户/权限表作为数据示例以及如何将其转换为 CouchDB。它似乎并没有解决实际限制对资源的访问的问题。 另外,我知道列表的目的主要是为了改变格式,我知道它们也用于过滤 B-tree,对吧? 你说得对,这篇文章没有提供权限问题的完整解决方案,但这是一个很好的起点,如图所示,你可以使用“权限”结构来保存视图可用于某一特定用户。我不知道列表/B-tree 关系,但我现在正在寻找它。您是否有任何链接可以更详细地解释它? books.couchdb.org/relax/appendix/btrees 解释了 B 树是如何(基本上)实现的。 我的意思是:视图提供对键的排序和过滤线性。如果您想在该视图中进行额外过滤,您需要一个列表,对吗?我还不完全明白,但这是我从你参考的书中收集到的。 我更新了一点我的答案。是的,我认为使用列表可以限制对某些资源的访问。

以上是关于CouchDb 使用列表读取身份验证的主要内容,如果未能解决你的问题,请参考以下文章

我应该为在 CouchDB 上运行的 Rails 3 使用哪个身份验证 gem/插件?

couchdb - 将遗留身份验证模块集成到 couchapp

ios 的 couchdb 中的身份验证

Cloudant 身份验证:缺少 _users 数据库

用户无法为 _session 进行身份验证

PouchDB 身份验证触发 CORS 预检请求