Firebase 数据库规则时间戳问题

Firebase Database Rules Timestamp Issue

自从 2017 年 10 月 29 日的时移以来,我在使用 firebase 产品进行开发时 运行 出现了一些非常奇怪的行为。

我正在使用 Ionic (3) 开发混合应用程序。当我在浏览器(移动模拟设备)中开发和测试时,一切正常。一旦我切换到我的真实设备(Samsung Galaxy S7,没有 root,modded 或其他东西),所有带有时间戳的数据库写入都会失败。

在我的代码中,我创建了一个这样的时间戳:Date.now()

在我的 firebase 规则中,我通常像这样验证时间戳:

"timestamp": { ".validate": "newData.isNumber() && newData.val() <= now" }

对我来说这条规则意味着,要写入数据库的新数据必须是一个数字,并且新数据的值必须小于或等于当前服务器时间戳。如果这些条件之一不匹配,它将向客户端发出警告。

我花了一整天的时间调试我的代码并找到了错误。当我删除(注释掉)时间戳相关规则上的 .validate 键时,一切正常。

所以我对 firebase 规则中的时间戳值进行了一些尝试。例如,我向服务器时间戳添加了一个小缓冲区,如:(now + 10000) (10secs).

突然间它起作用了。我降低了该值,直到它在我的真实设备上停止工作。我停在 (now + 5000)(5 秒)。

所以现在我的问题是,为什么会出现这种行为。

在时间转移之前,一切正常。以我的理解,客户端时间戳不可能领先于服务器时间戳。 (真机本地时间为用户自行修改除外)

寻求帮助,额外 5 秒的解决方法似乎有点脏。

干杯 未知0wn0x

顺便说一句:每次我修改 firebase 规则并将它们部署到服务器时,我都等了大约五分钟。

感谢您的注释。

我又玩了一次时间戳并弄清楚了不需要的行为。

这是我添加到我的函数中的代码,想要将时间戳写入数据库:

const test  = Date.now();
const test2 = new Date().getTime();
console.log('server offset: ', snap.val());
console.log('Date.now(): ', test);
console.log('new Date().getTime(): ', test2);
console.log('estimated server timestamp (new Date().getTime() + offset): ', (test2 + snap.val()));
console.log('client timestamp (Date.now() - offset): ', (test - snap.val()));

以上代码的输出:

server offset: -2427
Date.now(): 1509730244926
new Date().getTime():  1509730244926
estimated server timestamp (new Date().getTime() + offset): 1509730242499
client timestamp (Date.now() - offset): 1509730247353

这里的关键是负偏移。我从客户端时间戳中减去服务器偏移量以获得时间戳,该时间戳小于估计的服务器时间戳。

但是:--+。所以我不小心把它们加在一起,而不是互相减去。

我已经执行了几次我的函数并且可以确定,偏移量是从执行到执行不同的。一次 +77 ms 另一次 -2427ms, 等等..

所以我添加了一个小代码片段,它检查返回的服务器偏移量是正数还是负数,以便能够正确计算客户端时间戳。

const serverOffset: number = snap.val();
let clientTimestamp: number = null;

if (Math.sign(serverOffset) === 1){
    clientTimestamp = Date.now() - serverOffset;
} else if (Math.sign(serverOffset) === -1){
    clientTimestamp = Date.now() + serverOffset;
}

clientTimestamp 现在可以正常工作了。

如 Firebase 文档中所述,如果仅将偏移量添加到客户端时间戳,也可以实现此行为。

也许应该在 Firebase Docs 中提到,偏移量也可以是负数而不仅仅是正数。如果本地设备时间比从 Internet 获取的时间晚一秒钟,则可以轻松重现此行为。

但为什么会突然发生,而且以前从来没有发生过?