基于每个数据库的CouchDB授权

时间:2010-10-29 19:59:12

标签: security couchdb

我正在开发CouchDB支持的应用程序。基本上,我想为我的应用程序的每个用户创建一个数据库。为此,admin用户将创建数据库,但是在此之前,用户需要访问他们的数据库(使用SSL Auth over SSL)。我一直都在想着解决这个问题。

我找到的最好的资源是CouchDB wiki,在这个链接:

http://wiki.apache.org/couchdb/Security_Features_Overview#Authorization

它建议您可以通过创建名为“_security”的文档来设置每个数据库的授权,您可以在其中添加管理员和读者的哈希值。当我尝试创建该文档时,我收到的消息是“Bad special document member:_security”。

$ curl -X GET http://localhost:5984
{"couchdb":"Welcome","version":"1.0.1"}

任何帮助将不胜感激!

干杯,

亚伦。

3 个答案:

答案 0 :(得分:47)

这种方法应该没有问题。

假设您有一个数据库“test”,并且已经拥有一个管理员帐户:

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"

此用户使用带有盐“1”(sha1(“123”+“1”))的sha1对密码“123”进行哈希处理,因此他可以读取数据库:

curl -X GET http://localhost:5984/test -u "joe:123"

他现在可以在该数据库上阅读任何文档,而其他用户(但他和管理员)都无法阅读。

更新:作家安全

上述方法会引发读者问题,但此处的读者权限实际上是指“读/写常用文档”,因此它允许编写除了design-docs之外的文档。 _security doc中的“admin”允许在此数据库中编写设计文档。

根据您自己的回答,另一种方法是“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”,然后对其进行身份验证。

答案 1 :(得分:5)

我一直在做更多的研究和测试,我想总结一下我去过哪里,以及什么仍然不适合我。

首先,对于那些阅读此问题的人道歉:我一直在寻找为人们设置写入数据库而不是读取数据库的权限的方法。事实证明这是一个很大的不同:创建“读者”的技术完全不同于创建“作家”(该术语实际上不存在,但我想知道为什么)。

简而言之:您必须将用户添加到_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_pa​​ssword值:

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 var。但对于我新创建的用户,它失败了:

$ 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哈希为空。我想知道这个名称空间是否导致问题?它里面有一个怪异的冒号,所以也许有一些关于密码的混淆?我试过没有命名空间,但它根本不起作用;至少在这里,我的请求似乎正在访问数据库并得到回复。

我在这一点上陷入困​​境。如果有人能够检查我的假设和进展到目前为止,我希望我们都能弄清楚如何使这项工作。

谢谢!

亚伦。

答案 2 :(得分:0)

您可能需要查看Matt Woodward的 - CouchDB身份验证和安全权威指南http://blog.mattwoodward.com/2012/03/definitive-guide-to-couchdb.html