恢复规则:验证数据没有字段



所以我目前为所有用户提供了两个角色:isAdmin和isReader。

允许管理员读取和写入数据,允许读取者读取数据。

当有人创建一个帐户时,他没有权利。甚至没有isReader.只有管理员可以更改规则。

这就是我计划的做法:

一旦有人创建了一个帐户,我就会在Users集合中创建一个文档,如下所示:

uid: user.uid,
email: user.email,
role: {
isAdmin: false,
isReader: false,
}

每次登录时,我都会更新"电子邮件"并uidrole保持不变。为了确保这种行为,我有以下规则:

match /Users/{userId} {
allow read: if isOwner(userId) || isAdmin();
allow create: if request.resource.data.hasAll(['uid', 'email', 'role']) && request.resource.data.role.isAdmin == false && request.resource.data.role.isReader == false;
allow update: if resource.data.role == null || isAdmin();
}
function isAdmin() {
return getUserData().role.isAdmin == true;
}

我想我有 2 个错误:

  1. 由于某种原因,data.hasAll(['uid', 'email', 'role'])不起作用。当我删除此部分时,create规则按计划工作。

  2. resource.data.role == null不起作用。我打算检查数据是否包含任何role更新,因为我不允许它不是来自管理员。但由于某种原因它不起作用。

知道我做错了什么吗?另外,我的策略是否保存,或者是否有办法"破解"自己的读者或管理员权限?

这看起来可能是自定义身份验证声明的一个很好的用例。您可以在安全环境中为用户设置特定角色,如此 Codelab 所示。下面是在服务器中设置自定义声明的示例。您甚至可以为此使用云函数。我建议您查看 Codelab 的完整代码,以便了解如何确保不是任何人都可以请求将自定义声明添加到他们的用户中。

admin.auth().setCustomUserClaims(uid, {Admin: true}).then(() => {
// The new custom claims will propagate to the user's ID token the
// next time a new one is issued.
});

然后,您可以在安全规则中检查用户的这些角色。

service cloud.firestore {
match /databases/{database}/documents {
match /Users/{userId} {
allow read: if request.auth.token.Owner == true || request.auth.token.Admin == true;
allow create: request.auth.uid == userId && 
request.resource.data.uid == request.auth.uid &&
request.resource.data.email != null;
allow update: request.auth.uid == userId || request.auth.token.Admin == true;
}
}
}

请注意,有关"角色"的所有规则都已删除,因为它们不再需要。如果您对实施有疑问,请告诉我,因为我正在尝试围绕此问题制作更多内容,因为这是一个常见问题。

request.resource.data.hasAll(['uid', 'email', 'role'])

不起作用,因为request.resource.dataMap而不是List。应使用keys()Map创建List,并确保某些密钥存在。

关于你的第二个问题,你应该检查是否有写信给rolesallow update: if !('roles' in request.writeFields) || isAdmin();。这将确保对roles的任何更新都将失败,除非用户是管理员。

关于您的安全问题;我看到几个问题。首先是任何人都可以创建无限的用户,这也意味着任何管理员都可以创建无限的其他管理员帐户。为了阻止这种情况发生,我会在allow create中添加另一个部分,将创建限制为用户:

allow create: if userId == request.resource.data.uid
&& request.auth.uid == request.resource.data.uid
&& request.resource.data.hasAll(['uid', 'email', 'role'])
&& request.resource.data.role.isAdmin == false
&& request.resource.data.role.isReader == false;`

第二个是任何人都可以改变他们的uid并尝试冒充别人。显然,这不会改变与其身份验证令牌关联的uid,但根据您如何编写其余规则、后端安全性甚至前端显示,有人可能会利用该缺陷来利用您的代码或其他用户(可能是管理员(。您可以通过检查其uid是否在writeFields中来确保没有人更改其(您还需要以前的安全解决方案,以确保他们在创建过程中不会模拟(。

allow update: if !('uid' in request.writeFields)
&& (!('roles' in request.writeFields) || isAdmin());

我希望这有所帮助。

最新更新