Google cloud firestore Firestore安全规则get()不工作
在firestore中,我希望用户仅在文档中提到的Google cloud firestore Firestore安全规则get()不工作,google-cloud-firestore,firebase-security,Google Cloud Firestore,Firebase Security,在firestore中,我希望用户仅在文档中提到的teamid中访问文档。现在我有一个名为teams的不同集合,其中用户映射为{user\u id=true}。所以我在Firestore规则中有以下内容 return get(/databases/$(database)/documents/teams/$(resource.data.teamid)).data.approvedMembers[request.auth.uid] == true; 现在,此规则不起作用,前端对数据库的任何请求都会
teamid
中访问文档。现在我有一个名为teams
的不同集合,其中用户映射为{user\u id=true}
。所以我在Firestore规则中有以下内容
return get(/databases/$(database)/documents/teams/$(resource.data.teamid)).data.approvedMembers[request.auth.uid] == true;
现在,此规则不起作用,前端对数据库的任何请求都会失败。但当我用实际的teamid
值替换$(resource.data.teamid)
时,如下所示
return get(/databases/$(database)/documents/teams/234234jk2jk34j23).data.approvedMembers[request.auth.uid] == true;
。。。它按预期工作
现在我的问题是,我是否以错误的方式使用资源
,或者在Firestore规则中的get()
或exists()
查询中不支持资源
编辑
完成以下规则
service cloud.firestore {
match /databases/{database}/documents {
function isTeamMember() {
return get(/databases/$(database)/documents/teams/$(resource.data.teamid)).data.approvedMembers[request.auth.uid] == true;
// return exists(/databases/$(database)/documents/teams/$(resource.data.teamid));
}
match /{document=**} {
allow read, write: if isTeamMember();
}
}
}
如果您注意到注释掉的规则,
exists()
在这种情况下也不起作用。您有一个匹配的:
match /{document=**} {
allow read, write: if isTeamMember();
}
这将匹配数据库中的任何文档。这意味着当您调用isTeamMember()
时,不能保证resource
代表团队
文档。如果您在团队中有任何子集合
并向这些子集合写信,则资源
将成为子集合文档。感谢您在Twitter上联系。在我们的交谈之后,以下是结论:
使用安全规则查询文档
不能将安全规则用作筛选器。要使其正常工作,还必须添加。其中('teamid','==',yourTeamId)
您已经确认这对您有效,但您并不总是希望限制一个teamid
使用自定义声明
您可以在身份验证令牌中设置自定义声明。下面是一个如何设置这些规则并在规则中使用它们的示例
设置自定义声明
为此,您需要使用AdminSDK
auth = firebase.auth();
const userId = 'exampleUserId';
const customClaims = {teams: {myTeam1: true, myTeam2: true}};
return auth.setCustomUserClaims(userId, customClaims)
.then(() => {
console.log('Custom claim created');
return auth.getUser(userId);
})
.then(userRecord => {
console.log(`name: ${userRecord.displayName}`);
console.log(`emailVerified: ${userRecord.emailVerified}`);
console.log(`email: ${userRecord.email}`);
console.log(`emailVerified: ${userRecord.emailVerified}`);
console.log(`phoneNumber: ${userRecord.phoneNumber}`);
console.log(`photoURL: ${userRecord.photoURL}`);
console.log(`disabled: ${userRecord.disabled}`);
console.log(`customClaims: ${JSON.stringify(userRecord.customClaims)}`);
})
.catch(err => {
console.error(err);
});
应用安全规则
我仍然不能100%确定这是否也需要您按teamid
进行筛选。请测试并反馈。您是对集合中的多个文档执行查询,还是提取单个文档?嘿@Toddkerpman。是的,我正在查询多个文档。您能否显示更多规则,包括适用的match
和allow get
语句?@SamStern我在问题中添加了完整的规则isTeamMember()
将对每个文档运行。但这是我们的初衷。它只需要访问请求资源中的teamid
。现在,我们已经有意识地决定在每个集合和子集合的每个文档中包含teamid
,每个集合中的每个文档都有teamid
。那么查询不应该起作用吗?
allow read, write: if request.auth.token.teams.$(resource.data.teamId) == true;