概述
Couchdb 在配置中而不是在数据库中设置管理员设置的一个覆盖级别,并分配了权限以防止任何被锁定的可能性。_users
_admin
然后,每个单独的数据库都有一个粗略的 2 级安全策略:
- 管理员
- 会员
通过指定:
- 名字
- 角色
制作4个字段。
对于 db 可以包含的两种类型的文档,这些级别对访问的控制略有不同:
- id:
_design/*
- 设计文档可以包含将在某些上下文中执行的功能
- id:
other
- 普通文档只是普通数据
两种级别的数据库访问都对数据库中的所有文档具有读取权限,但管理员对 _design 文档具有写入权限。对普通文档的写访问权限通常授予所有被授予对 db 的任何访问权限的用户,但可以通过validate design documents进行限制。
总结
设置唯一安全策略的过程是:
- 在设置 _users 时,以消费者身份体验提供的验证设计文档。
- 设置新数据库及其基本安全性,为您的用户提供成员访问权限。
- 使用限制成员写访问的验证功能将设计文档添加到新数据库。
1 设置 _users 条目
为用户添加角色
作为管理员添加role: ["logger"]
到用户的文档并保存,请注意,由于默认 _users 设计文档的这一部分,这必须由管理员完成:
// DB: _users doc: _design/_auth
function(newDoc, oldDoc, userCtx, secObj) {
..
if (oldRoles.length !== newRoles.length) {
throw({forbidden: 'Only _admin may edit roles'});
}
更改用户的密码。
管理员或用户都可以通过password:"mynewpassword"
在他们的文档中设置来更改他们的密码(在保存过程中,couchdb 将转换为哈希/加盐密码)。这适用于用户,因为他们可以添加/修改除姓名和角色之外的字段,只要用户正在编辑自己的文档:
// DB: _users doc: _design/_auth
function(newDoc, oldDoc, userCtx, secObj) {
..
if (userCtx.name !== newDoc.name) {
throw({
forbidden: 'You may only update your own user document.'
});
}
// then checks that they don't modify roles
您可以对分配adminlogger
角色的用户重复此过程以创建委派管理员,您可以分配权限以重新配置数据库,或者您可以继续使用 couchdb 管理员及其_admin
角色进行所有管理。
2 设置新数据库及其基本安全性
创建一个名为 logger 的数据库,为 logger 分配一个安全策略:
{
"admins": {
"names": [
],
"roles": [
"adminlogger"
]
},
"members": {
"names": [
],
"roles": [
"logger"
]
}
}
作为 _admin 用户或具有该adminlogger
角色的用户,通过复制 _users 设计文档、删除 _rev 并修改函数来创建新的验证设计文档:
// DB: logger doc: _design/auth
function(newDoc, oldDoc, userCtx, secObj) {
// Don't let non-admins write a pre-existing document:
if (!is_server_or_database_admin()) {
if (!!oldDoc) {
throw({
forbidden: 'You may not update existing documents.'
});
}
}
// Where the function to define admins can be copied verbatim from the doc:
var is_server_or_database_admin = function(userCtx, secObj) {
// see if the user is a server admin
if(userCtx.roles.indexOf('_admin') !== -1) {
return true; // a server admin
}
// see if the user a database admin specified by name
if(secObj && secObj.admins && secObj.admins.names) {
if(secObj.admins.names.indexOf(userCtx.name) !== -1) {
return true; // database admin
}
}
// see if the user a database admin specified by role
if(secObj && secObj.admins && secObj.admins.roles) {
var db_roles = secObj.admins.roles;
for(var idx = 0; idx < userCtx.roles.length; idx++) {
var user_role = userCtx.roles[idx];
if(db_roles.indexOf(user_role) !== -1) {
return true; // role matches!
}
}
}
return false; // default to no admin
}
}
如果您按照这些步骤操作,那么您在步骤 1 中赋予记录器角色的用户可以运行您的代码以仅在步骤 2 和 3 中配置的记录器数据库中写入新文档。