Firebase:无法添加用户条目(`set` 权限被拒绝)
Firebase: Cannot add user entry (`set` permission denied)
我想确保可以(从客户端)创建新用户,但只有经过身份验证的用户才能读取或写入现有对象。
我有一个简单的规则集:
{
"rules": {
"users": {
"$uid": {
".read": "auth != null && auth.uid === $uid",
".write": "!data.exists() || auth.uid === $uid"
}
}
}
}
我正在调用 createUser
,然后在回调中我试图向我自己的 users
对象添加一个条目:
const usersRef = ref.child('users');
const userEntry = {
[userData.uid]: {
created: new Date().getTime()
}
};
usersRef.set(userEntry)
我本以为即使用户还没有登录,他们也应该有写权限,因为!data.exists()
。但是我收到 PERMISSION_DENIED
错误。
如果我在 users
级别上设置 ".write": true
那么它会级联(并覆盖?)我的内部规则不是吗?
编辑:
即使在以下情况下也会失败:
"users": {
"$uid": {
".read": true,
".write": true
}
}
谢谢。
我想我最初误解了这个问题。在您当前的回调中,由于 set 的工作方式,您正试图覆盖整个用户级别。
你真的只想设置不存在的东西:
const userRef = ref.child('users').child(userData.uid);
const userEntry = {
created: new Date().getTime()
};
userRef.set(userEntry);
那么,我认为您现有的规则会起作用。
我认为这是一个令人困惑的问题,因为创建用户和写入数据库是完全不同的事情。所以我只会在我的应用程序中展示我是如何做到的。
- 第一步是creating the user
- 下一步log the user in因为创建不会自动登录用户(我在创建用户的回调函数中这样做)
- 最后一步是 writing the user data to firebase
我使用以下规则来确保每个用户只能在 firebase 中写入他自己的节点 (documentation):
{
"rules": {
"users": {
"$user_id": {
".write": "$user_id === auth.uid"
}
}
}
}
要记住的一件事是 set() 将替换该路径上的任何现有数据。因此,请确保使用用户的 uid 而不是用户节点。
最后我想指出您在问题中发布的规则中的一个巨大缺陷:
".write": "!data.exists() || auth.uid === $uid"
此规则规定,如果还没有任何数据或者您有正确的 uid,您可以写入。该语句的第一部分是问题所在,因为 ANYONE 可以在没有任何数据时写入该位置。另外因为 $uid 是一个 dynamic path 你可以在那里添加任何东西,比如:
"users": {
"WoWIjustMadeThisUp": {
"nice": "Some huge value making you go over your limit"
}
}
如果您希望用户只写一个初始值,之后将无法编辑它,只需使用 validate rule to check if there is already data at that location。
我想确保可以(从客户端)创建新用户,但只有经过身份验证的用户才能读取或写入现有对象。
我有一个简单的规则集:
{
"rules": {
"users": {
"$uid": {
".read": "auth != null && auth.uid === $uid",
".write": "!data.exists() || auth.uid === $uid"
}
}
}
}
我正在调用 createUser
,然后在回调中我试图向我自己的 users
对象添加一个条目:
const usersRef = ref.child('users');
const userEntry = {
[userData.uid]: {
created: new Date().getTime()
}
};
usersRef.set(userEntry)
我本以为即使用户还没有登录,他们也应该有写权限,因为!data.exists()
。但是我收到 PERMISSION_DENIED
错误。
如果我在 users
级别上设置 ".write": true
那么它会级联(并覆盖?)我的内部规则不是吗?
编辑:
即使在以下情况下也会失败:
"users": {
"$uid": {
".read": true,
".write": true
}
}
谢谢。
我想我最初误解了这个问题。在您当前的回调中,由于 set 的工作方式,您正试图覆盖整个用户级别。
你真的只想设置不存在的东西:
const userRef = ref.child('users').child(userData.uid);
const userEntry = {
created: new Date().getTime()
};
userRef.set(userEntry);
那么,我认为您现有的规则会起作用。
我认为这是一个令人困惑的问题,因为创建用户和写入数据库是完全不同的事情。所以我只会在我的应用程序中展示我是如何做到的。
- 第一步是creating the user
- 下一步log the user in因为创建不会自动登录用户(我在创建用户的回调函数中这样做)
- 最后一步是 writing the user data to firebase
我使用以下规则来确保每个用户只能在 firebase 中写入他自己的节点 (documentation):
{
"rules": {
"users": {
"$user_id": {
".write": "$user_id === auth.uid"
}
}
}
}
要记住的一件事是 set() 将替换该路径上的任何现有数据。因此,请确保使用用户的 uid 而不是用户节点。
最后我想指出您在问题中发布的规则中的一个巨大缺陷:
".write": "!data.exists() || auth.uid === $uid"
此规则规定,如果还没有任何数据或者您有正确的 uid,您可以写入。该语句的第一部分是问题所在,因为 ANYONE 可以在没有任何数据时写入该位置。另外因为 $uid 是一个 dynamic path 你可以在那里添加任何东西,比如:
"users": {
"WoWIjustMadeThisUp": {
"nice": "Some huge value making you go over your limit"
}
}
如果您希望用户只写一个初始值,之后将无法编辑它,只需使用 validate rule to check if there is already data at that location。