Firebase 数据库:如果客户端处于离线状态,显然规则不适用?



请考虑以下示例:

我正在test/节点上写入一个值,并且我已经设置了一个规则,仅当"(新值)等于(旧值 + 1)"时,才允许写入,即newData.val() == data.val() + 1

假设test/节点的初始值为0

如果客户端脱机并执行以下命令:

testRef.setValue(1);
testRef.setValue(2);
testRef.setValue(3);
testRef.setValue(4);
testRef.setValue(5);

然后当他重新上线时,5的值将写入数据库中,但我不确定我是否理解为什么,因为5 != 0 + 1.我想这是由于在本地数据库中缓存了以前的值而发生的,但不幸的是,这不是我想要实现的结果。我希望服务器拒绝该值,因为它不遵循数据库的规则。

有没有办法实现这一目标?

或者是否有任何其他解决方法,以便我可以实现以下内容:

testRef.setValue(1);->将值写入本地数据库->检查值是否遵循联机数据库的规则->如果值不符合规则,或者如果我们因为离线而无法检查,则从本地数据库中删除该值

我假设对于您的问题,"离线"意味着客户端没有连接。 在我的测试中,我通过启用飞行模式来模拟它。

用户指南中介绍了 Firebase 离线功能。那里提供的一个对您的问题很重要的细节是:

Firebase 实时数据库客户端会自动保留 应用脱机时执行的所有写入操作... 当应用重新获得连接时,所有操作都将发送到 Firebase 实时数据库服务器。

可以使用下面的代码查看此行为,该代码将完成侦听器添加到setValue()调用。在我的测试中,我将设备置于飞行模式(离线),运行代码,然后禁用飞行模式以重新联机。 每setValue()都会生成一条日志消息,确认写操作在重新建立连接时已排队并发送。 这就解释了为什么写入满足验证规则:客户端不会发送一个最终值为 5 的写入请求,而是发送五个具有原始递增值的请求。

您可以通过再次运行测试来确认规则是否有效,而无需先将test的值重置回 0。 每次写入都将失败。

此代码还演示了 Firebase 客户端如何处理客户端离线时所做的更改,以及稍后被安全规则拒绝的更改。 脱机时,将在客户端缓存中进行更改,并使用新的(未经验证的)值触发onDataChange()回调。 稍后,当客户端联机并且更改被服务器拒绝时,onDataChange()会再次使用以前的值触发。

final DatabaseReference ref = FirebaseDatabase.getInstance().getReference("test");
ref.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
Log.d(TAG, "onDataChange: test=" + dataSnapshot.getValue(Integer.class));
}
@Override
public void onCancelled(DatabaseError databaseError) {
throw databaseError.toException();
}
});
final DatabaseReference.CompletionListener completionListener =
new DatabaseReference.CompletionListener() {
@Override
public void onComplete(DatabaseError databaseError, DatabaseReference databaseReference) {
if (databaseError == null) {
Log.d(TAG, "setValue() Success");
} else {
Log.d(TAG, "setValue() Failed " + databaseError.getMessage());
}
}
};
ref.setValue(1, completionListener);
ref.setValue(2, completionListener);
ref.setValue(3, completionListener);
ref.setValue(4, completionListener);
ref.setValue(5, completionListener);

最新更新