gpt4 book ai didi

Firebase 实时数据库规则 : Validation is cascading to child. 如何忽略父节点上的 .validate?

转载 作者:行者123 更新时间:2023-12-04 17:08:49 24 4
gpt4 key购买 nike

我正在尝试编写 firebase 实时数据库规则,首先,如果 $gameID 恰好有 6 个字符并且 $gameID 没有,则允许创建一个新游戏' 已经存在于 games 节点上。在创建新游戏时,这条规则实际上非常有效。

当玩家随后尝试加入该游戏时,问题就来了:上述验证规则拒绝了他们,因为它要求游戏不存在 - 但我只想要该规则 — "$gameID.length === 6 && !data.exists()" — 仅在 games/$gameID 上验证写入,而不是在 games/$gameID/players 上验证。

我的理解是 .validate 规则不会向下级联,那么为什么不允许写入 games/$gameID/players

我当前的 database.rules 文件是:

{
"rules": {
"games": {
"$gameID": {
".read": "auth !== null",
".write": "auth !== null",
".validate": "$gameID.length === 6 && !data.exists()",
"players": {
".read": "auth !== null",
".write": "auth !== null"
}
}
}
}
}

players 的 javascript 代码是:

await push(ref(db, `games/${gameID}/players`), playerName)

set 模拟拒绝 with .validate 规则($gameID 节点 ABC123 存在在数据库中): Denied with .validate rule

set 模拟允许没有 .validate 规则($gameID 节点ABC123 存在在数据库中): Allowed without .validate rule

最佳答案

当安全规则谈到“级联规则”时,这是指更高层的 ".read"".write" 规则将覆盖任何嵌套的行为规则(成功的更高层规则将覆盖失败的嵌套规则)。这与 ".validate" 规则形成对比,其中链中的每个规则都必须评估为 true 才能成功写入(成功的更高层规则不会覆盖嵌套规则失败)。

根据您的评论,您的数据如下所示:

{
"games": {
"abcdef": {
"players": {
"-MoSHoV6kC4cV_jCdssT": "player A",
"-MoSI4begYNOBYVmiVBi": "not player A",
"-MoSI5nVWYD5VnSaaWP0": "tom"
}
},
/* more rooms */
}
}

当前规则的问题在于您必须允许创建房间,并且还必须允许玩家加入该房间。正如您推断的那样,您的规则允许第一个操作,但阻止第二个操作。

要解决此问题,您需要对基于客户端的代码稍作调整,以便区分“我正在创建此房间”和“我正在加入此房间”操作。在当前结构下,我看不出这是怎么可能的,因为这两个操作之间没有任何区别 - 它们看起来都像:

SET /games/abcdef/players/-MoSHoV6kC4cV_jCdssT = "some user"
SET /games/abcdef/players/-MoSI4begYNOBYVmiVBi = "not player A"

应允许创建房间的请求中的哪一个?

为此,我们需要引入一种方法来告诉数据库“我正在创建这个房间”。我们可以通过添加一个新的“所有者”属性来做到这一点,该属性允许我们应用以下规则:

  • 如果所有者不存在,则允许创建房间。
  • 如果所有者已经存在,则拒绝创建房间。
  • 如果创建的房间没有所有者,则拒绝创建房间。
  • 如果房间是使用无效 ID 创建的,则拒绝创建房间。
  • 玩家只能由所有者添加/删除。

因为您的用户已登录,所以您应该使用他们的用户 ID 而不是推送 ID 来帮助以后保持房间安全,尽管即使您不切换,以下设置仍然有效。

{
"games": {
"abcdef": {
"players": {
"BzzmNyT7hlMz3ElRLMYS0jaGKgE3": "player A",
"BSfHksARFnYco5LenfxevOpnwe63": "not player A",
"vDnPE4DqE3cz1IYHwXQvDFw3W7r2": "tom"
},
"owner": "BzzmNyT7hlMz3ElRLMYS0jaGKgE3"
},
/* more rooms */
}
}

规则:

{
"rules": {
"games": {
"$gameID": {
// any authenticated user may read this entire room's data
// future: restrict to only members?
".read": "auth !== null",

// a room must have an ID of 6 characters
// and must have an owner assigned to it
".validate": "$gameID.length === 6 && newData.hasChild('owner')",

"players": {
// use $pushId here if keeping your "push" method instead of switching to user IDs
"$playerId": {
// only the owner may add/remove players
".write": "auth !== null && newData.parent().child('owner').val() == auth.uid",
// as long as the value is a string
".validate": "newData.isString()"
}
},

"owner": {
// an owner prop can be created, but not edited/deleted
".write": "auth !== null && !data.exists()"
// an owner prop must be the writer's user ID
".validate": "newData.isString() && newData.val() === auth.uid"
}
}
}
}
}

注意:上述规则对房间的所有者也是玩家的 Assets 没有任何影响。

关于Firebase 实时数据库规则 : Validation is cascading to child. 如何忽略父节点上的 .validate?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69921744/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com