Firebase 按预期拒绝使用 PermissionDenied 进行更新,但侦听节点的客户端仍会收到发送的数据
Posted
技术标签:
【中文标题】Firebase 按预期拒绝使用 PermissionDenied 进行更新,但侦听节点的客户端仍会收到发送的数据【英文标题】:Firebase rejects update with PermissionDenied as expected but still the client listening to the node receives the data sent 【发布时间】:2021-10-31 07:28:52 【问题描述】:我正在监听实时数据库中的一个节点,并且发送了一个不应通过安全规则的 MULTIPATH 更新。应该通过写规则而不是验证规则。
检查 firebase 控制台没有按预期写入。但是使用 onChildAdded 监听其中一个节点的客户端会收到发送的数据。
是否有可能没有任何东西被提交到数据库但仍然在客户端触发 onChildAdded?
我认为这是不可能的,但我可能遗漏了一些关于规则验证 + 多路径更新的内容。
收到的事件打印在控制台上:
事件:“查询事件”的实例 | event.snapshot: 'DataSnapshot' 的实例 | event.snapshot.val: c: true, m: e3, n: 1 [2021-08-31T18:14:33.230Z] @firebase/database: FirebaseError: PERMISSION_DENIED: Permission denied (PERMISSION_DENIED)
发送的数据,我是这样进行多路径更新的:
Map<String, dynamic> updateToSend = ;
updateToSend["status/c"] = move.c;
updateToSend["status/n"] = move.n;
updateToSend["moves/$move.n/n"] = move.n;
updateToSend["moves/$move.n/m"] = move.m;
updateToSend["moves/$move.n/c"] = move.c;
await fb.database().ref('games/$gameID').update(updateToSend);
听者:
final movesRef = fb.database().ref("/games/$gameId/moves");
final streamMoves = movesRef.onChildAdded;
streamMoves.listen((event)
print(
"event: $event | event.snapshot: $event.snapshot | val: $event.snapshot.val()");
...
【问题讨论】:
【参考方案1】:在执行写入操作的客户端上,受影响路径的侦听器会立即触发 - 甚至在数据发送到服务器之前。如果写入被服务器拒绝,SDK 实际上会触发协调事件以确保应用可以再次进入正确的状态。
所以:如果您也收听onChildRemoved
流,一旦服务器拒绝写入操作,您将在那里收到一个事件。这使您可以再次将其从 UI 中删除。无法阻止获取初始本地事件。
【讨论】:
执行写入的本地客户端上的事件包含服务器上时间的估计,该时间基于本地时间和本地时间到服务器的偏移量(它在第一次测量时测量)连接)。但是服务器永远不会看到/使用该值,而是使用实际的服务器端时间戳,然后它也会发送给所有客户端(包括最初写入该值的客户端)。然后,发起客户端应更新其 UI 以显示服务器端时间戳。这两个事件之间的差异通常很小。 谢谢!是的,我正在测试它,每次移动似乎有大约 50 毫秒的差异。我想我会看看如何同步它,谢谢 是的,50 毫秒的声音在预期范围内。如果您只是在本地 UI 中显示来自事件的值,则不需要做任何额外的工作。在这种情况下,这意味着您必须收听child_added
(对于带有客户端估计时间戳的本地快照)和child_changed
(对于带有服务器端确认时间戳的更新快照)。如果您这样做,用户将暂时看到一个稍微偏离的时间戳 - 但这通常不是问题。
太棒了!我现在就试试,谢谢!以上是关于Firebase 按预期拒绝使用 PermissionDenied 进行更新,但侦听节点的客户端仍会收到发送的数据的主要内容,如果未能解决你的问题,请参考以下文章
firebase onDisconnectSetValue 未按预期工作
Firebase onAuthStateChanged 在 React App 中未按预期运行