我想将用户的私人信息存储在 Cloudant 中的 CouchDB 上——即每个用户应该只能阅读和更新他自己的文档。通常此类信息保存在 _users 数据库中,但我真的很喜欢 Cloudant 的 API 密钥并且不想自己管理用户和密码。
我在这个 wiki 中找到了几个解决方案: http ://wiki.apache.org/couchdb/PerDocumentAuthorization 但它们都有局限性:
- “每个用户的数据库”管理起来真的很烦人。
- “智能代理”从 CouchDB 和 CouchApps 中获得乐趣。
- “基于每个用户的文档加密”太复杂了。
然后我想出了一个新的解决方案——我创建了一个数据库(称为“test”)并将所有用户配置为_writer
s,没有任何_reader
s。为了防止用户互相覆盖文档,我设置validate_doc_update
了我_design/app
的 to:
function(newDoc, savedDoc, userCtx) {
if ((userCtx.roles.indexOf('_admin') < 0) && (userCtx.name != newDoc._id)) {
throw ({unauthorized: "cannot access others"});
}
}
为了让用户阅读自己的文档,我编写了以下更新函数(称为“update_hack”):
function(doc, req) {
return [doc, toJSON(doc)];
}
现在,每个用户都可以通过向以下地址发送 POST 请求来“获取”他的文档:
http://<username>:<password>@<host>/db/_design/app/_update/update_hack/<username>
如果用户尝试向其他用户的文档发送 POST 请求,请说:
http://<username>:<password>@<host>/test/_design/app/_update/update_hack/someoneelse
{"error":"unauthorized","reason":"cannot access others"}
然后他会因为尝试“更新”文档而得到响应。
这个技巧有一些效率低下,因为每次用户“获取”他的文档时,文档的修订版都必须更改。还有通过发送 POST 请求来识别用户名是否存在的问题(如果文档不存在,将返回“null”)。
你在这个技巧中看到任何安全漏洞吗?
当通过 API 密钥生成用户时,是否有更好的方法来存储每个用户的私人文档?(即使有,我仍然认为我的把戏很酷)。