基于每个数据库的 CouchDB 授权
Posted
技术标签:
【中文标题】基于每个数据库的 CouchDB 授权【英文标题】:CouchDB Authorization on a Per-Database Basis 【发布时间】:2011-05-02 14:40:03 【问题描述】:我正在开发 CouchDB 支持的应用程序。本质上,我想为我的应用程序的每个用户创建一个数据库。为此,管理员用户将创建数据库,但接下来,用户将需要访问他们的数据库(使用基于 SSL 的 HTTP Auth)。我花了很长时间才弄清楚这一点。
我找到的最好的资源是在 CouchDB wiki 中,在这个链接上:
http://wiki.apache.org/couchdb/Security_Features_Overview#Authorization
它建议您可以通过创建一个名为“_security”的文档来设置每个数据库的授权,您可以在其中添加管理员和读者的哈希值。当我尝试创建该文档时,我收到的消息是“错误的特殊文档成员:_security”。
$ curl -X GET http://localhost:5984
"couchdb":"Welcome","version":"1.0.1"
任何帮助将不胜感激!
干杯,
亚伦。
【问题讨论】:
嗨 Aaron,您是如何在每次用户注册时创建一个新数据库的?您是否使用了其他层,例如 php、node、ruby?还是你想出了一个纯粹的 couchapp 方式? 【参考方案1】:这种方法应该没有问题。
假设您有一个数据库“测试”,并且已经有一个管理员帐户:
curl -X PUT http://localhost:5984/test -u "admin:123"
现在您可以为其创建一个 _security 文档:
curl -X PUT http://localhost:5984/test/_security -u "admin:123" -d '"admins":"names":[], "roles":[], "readers":"names":["joe"],"roles":[]'
它们只有用户“joe”才能读取数据库。要创建用户,您必须已经拥有 sha1 哈希密码:
curl -X POST http://localhost:5984/_users -d '"_id":"org.couchdb.user:joe","type":"user","name":"joe","roles":[],"password_sha":"c348c1794df04a0473a11234389e74a236833822", "salt":"1"' -H "Content-Type: application/json"
该用户的密码“123”使用 sha1 和 salt“1” (sha1("123"+"1")) 进行哈希处理,因此他可以读取数据库:
curl -X GET http://localhost:5984/test -u "joe:123"
他现在可以阅读该数据库上的任何文档,而其他用户(除了他和管理员)不能。
更新:作家安全
上面的方法会出现reader问题,但是这里的reader权限实际上是指“读/写通用文档”,所以它允许写除design-docs之外的文档。 _security 文档中的“管理员”可以在此数据库中编写设计文档。
另一种方法,取自您自己的答案,是“validate_doc_update”,您可以在文件中有一个 validate_doc_update,如下所示:
function(new_doc, old_doc, userCtx)
if(!userCtx || userCtx.name != "joe")
throw(forbidden: "Bad user");
并将其推入 couchdb 设计中:
curl -X PUT http://localhost:5984/test/_design/security -d " \"validate_doc_update\": \"function(new_doc,doc,userCtx) if(userCtx || userCtx.name != 'joe') throw(forbidden: 'Bad user')\"" --user 'admin:123'
他们“joe”可以使用基本身份验证写入数据库:
curl -X PUT http://localhost:5984/test/foobar -d '"foo":"bar"' -u 'joe:123'
正如您还提到的,您可以使用 _session api 获取用于身份验证的 cookie:
curl http://localhost:5984/_session -v -X POST -d 'name=joe&password=123' -H "Content-Type: application/x-www-form-urlencodeddata"
这将返回如下标题:
Set-Cookie: AuthSession=am9lOjRDRDE1NzQ1Oj_xIexerFtLI6EWrBN8IWYWoDRz; Version=1; Path=/; HttpOnly
因此,您可以在您的下一个请求中包含 cookie“AuthSession=am9lOjRDRDE1NzQ1Oj_xIexerFtLI6EWrBN8IWYWoDRz”,它们将通过身份验证。
【讨论】:
我应该更具体。我需要创建用户来写入 到数据库,而不是读取。但是我已经找到了一些答案,所以我现在正在更新我的答案...... 亚伦,很高兴看到你进步了。 _security 文档中的读者实际上也被允许写作(我认为这是一个非常错误的前导名称),除了设计文档。我已经更新了我的答案,以涵盖更多关于写入权限的信息,包括 validade_doc_update 和 session api。 我设置了一些阅读器用户。我正在尝试弄清楚如何让他们进行身份验证。基本身份验证适用于 curl。我是否设置了另一个数据库来进行身份验证(每个人都可以阅读)?然后重定向,一个db的_rewrite指向另一个db的_rewrite?【参考方案2】:我一直在做更多的研究和测试,我想总结一下我已经到了哪里,还有什么对我不起作用。
首先,向阅读此问题的人道歉:我一直在寻找方法来设置人们写入而不是读取数据库的权限。事实证明这是一个很大的区别:创建“阅读器”的技术与创建“作者”的技术完全不同(这个术语实际上并不存在,尽管我想知道为什么)。
简而言之:您必须将用户添加到 _users 数据库,该数据库是有权访问您的 CouchDB 实例中的任何数据库的用户列表。我可以通过发出类似于以下的命令来做到这一点:
curl -X PUT http://admin:password@localhost:5984/_users/org.couchdb.user:username -d '"type":"user", "hashed_password":"2bf184a2d152aad139dc4facd7710ee848c2af27", "name":"username", "roles":[]'
请注意,您显然需要使用“org.couchdb.user”前缀为用户名命名空间。我使用了 Ruby 散列方法来获取 hashed_password 值:
require 'digest/sha1'
pass_hash = Digest::SHA1.hexdigest(password)
这会让一个明显有效的用户进入数据库。下一步是将该用户指定为我创建的新数据库的“作者”(哈,又来了!)。所以我可能会这样做:
curl -X PUT http://admin:password@localhost:5984/newdatabase
然后
curl -X PUT http://admin:password@localhost:5984/newdatabase/_design/security -d @security.json
该 .json 文件包含一个用于“validate_doc_update”键的 javascript 函数,该函数如下所示:
function(new_doc, old_doc, userCtx)
if(userCtx.name != username)
throw(forbidden: "Please log in first.");
这是一个环形交叉路口,但它是有道理的。但是,我现在遇到了一个问题:显然 userCtx 变量在用户通过身份验证之前不会被填充。 This article 建议您只需通过 HTTP 请求将凭据传递给特殊的 _session 数据库,如下所示:
curl -X POST http://username:password@localhost:5984/_session
我可以为我的管理员用户执行此操作,并且 userCtx 变量将被填充。但是对于我新创建的用户,它失败了:
$ curl http://org.couchdb.user:username:password@localhost:5984/_session
"ok":true,"userCtx":"name":null,"roles":[],"info":"authentication_db":"_users","authentication_handlers":["cookie","oauth","default"]
注意 userCtx 哈希为空。我想知道那个命名空间的东西是否导致了问题?它里面有一个怪诞的冒号,所以也许密码有些混乱?我试过在没有命名空间的情况下制作它,但它根本不起作用;至少在这里我的请求似乎正在访问数据库并得到响应。
我被困在这一点上。如果有人可以检查我迄今为止的假设和进展,我希望我们都能弄清楚如何使这项工作发挥作用。
谢谢!
亚伦。
【讨论】:
如果您查看 Futon 登录和注销控件正在做什么,您会看到用户可以登录到您的应用程序的通用方式。如果您通过 curl 访问,您可以通过在 Futon 中注册来创建用户。 身份验证时不需要“org.couchdb.user”前缀,它只是添加到_id用于存储在_users db中。只需curl http://username:password@localhost:5984/_session
,您应该会得到一个 userCtx 对象。【参考方案3】:
您可能需要查看 Matt Woodward 的 - The Definitive Guide to CouchDB Authentication and Security http://blog.mattwoodward.com/2012/03/definitive-guide-to-couchdb.html
【讨论】:
以上是关于基于每个数据库的 CouchDB 授权的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 javascript 在 couchdb 中使用多个组合键进行查询,而无需为每个组合编写单独的视图?
同一设备上的每个用户一个pouchDB与单个CouchDB同步