CouchDb使用列表读取身份验证

时间:2010-08-20 14:00:51

标签: authentication couchdb

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

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

建议elsewhere为不同的读者组使用不同的数据库,或者在另一个(中间)层中实现读者身份验证,这两个都不是这个项目的选项,其中访问权限由复杂的,每个文档ACL。

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

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可以实现这么简单的解决方案吗?

4 个答案:

答案 0 :(得分:5)

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

根据couchdb中的数据实施安全策略是完全没问题的。但是,成本是您负责实施的正确性。它没有听起来那么糟糕。请记住,很长一段时间以来,人们一直在使用MySQL网络应用程序。

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

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

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

希望能够解释为什么读控制处于数据库级别。

答案 1 :(得分:4)

通常足以限制对某些视图的访问 - 这可以通过您提议的列表来完成(感谢您的想法)。对文档使用不可识别的ID,您已经拥有某种文档访问控制。我会避免遍历行并检查那里的权限,但我不认为这也是一个问题。

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

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

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

  1. 您将用户名作为参数传递给视图并相应地进行过滤。
  2. 在使用视图的列表中,检查给定的参数用户名是否与实际用户相同。
  3. 据我所知,CouchDB内部使用缓存来查看视图。我不确定缓存如何与列表一起使用。另外我认为在视图中迭代和过滤通常比在列表中更快。

答案 2 :(得分:2)

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

首先,你需要CouchDB前面的东西阻止任何读取请求,这不会通过实现ACL的列表fn。 _all-docsreduce=true的请求,直接的文档GET - 全部以及许多其他请求必须被阻止。最简单的方法是使用Apache和regexp掩码。

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

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

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

答案 3 :(得分:1)

我不确定使用list是限制资源访问的最佳选择,因为list是用于以特定格式呈现视图的ouupt的函数(RSS,CSV,配置文件,HTML,... )。

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

alt text

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

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