面试题答案
一键面试1. 确保租户数据隔离
- 视图设计:在CouchDB中,为每个文档添加一个
tenant_id
字段,用于标识该文档所属的租户。例如,假设文档结构如下:
{
"_id": "doc1",
"tenant_id": "tenant1",
"data": "some data"
}
然后设计一个视图,以 tenant_id
作为键。在 map
函数中:
function(doc) {
if (doc.tenant_id) {
emit(doc.tenant_id, doc);
}
}
这样,当不同租户的用户查询时,只要在查询视图时指定自己的 tenant_id
,就能确保只获取到自己租户的数据。例如,使用CouchDB的HTTP API查询时:/db/_design/tenant_view/_view/by_tenant?key="tenant1"
就只会返回 tenant1
租户的数据。
- 安全控制逻辑:在CouchDB的
_security
文档中,限制每个租户的用户只能访问自己租户的数据库。例如,对于tenant1
租户的数据库tenant1_db
,_security
文档可以如下设置:
{
"admins": {
"names": [],
"roles": []
},
"members": {
"names": ["tenant1_user1", "tenant1_user2"],
"roles": []
}
}
这样只有 tenant1_user1
和 tenant1_user2
等属于 tenant1
租户的用户能访问 tenant1_db
数据库,从数据库层面保证了租户间的数据隔离。
2. 同一租户内不同权限用户看到对应权限的数据
- 视图设计:在文档中添加
permission
字段来表示数据的权限级别。例如:
{
"_id": "doc2",
"tenant_id": "tenant1",
"permission": "admin",
"data": "sensitive data"
}
设计一个复合视图,以 tenant_id
和 permission
作为键。map
函数如下:
function(doc) {
if (doc.tenant_id && doc.permission) {
emit([doc.tenant_id, doc.permission], doc);
}
}
这样不同权限的用户在查询时,可以通过指定不同的键来获取对应权限的数据。例如,普通用户可以查询:/db/_design/permission_view/_view/by_permission?key=["tenant1", "user"]
,而管理员用户可以查询:/db/_design/permission_view/_view/by_permission?startkey=["tenant1", "user"]&endkey=["tenant1", "admin"]
,以获取所有用户可见的数据以及管理员特有的数据。
- 安全控制逻辑:在应用层,根据用户登录时的权限信息,构建相应的视图查询参数。例如,当普通用户登录时,应用程序只构建查询普通权限数据的请求;当管理员用户登录时,构建能获取所有权限数据的请求。同时,在数据库层面,结合
_security
文档,可以进一步限制用户对视图的访问。例如,在_security
文档中,对于特定视图的read
权限进行设置,只有对应权限的用户角色可以读取特定的视图。
{
"admins": {
"names": [],
"roles": []
},
"members": {
"names": ["tenant1_user1", "tenant1_user2"],
"roles": []
},
"views": {
"by_permission": {
"read": ["admin_role", "user_role"]
}
}
}
其中 admin_role
和 user_role
分别是管理员和普通用户的角色,通过这种方式确保不同权限用户只能访问到对应权限的数据视图。