Firestore v9 React项目中Timestamp时间校验被拒绝该如何解决?
问题原因
你当前的权限校验失败不是因为网络延迟偏差,是实现逻辑本身就不匹配:
- 客户端代码里的
Timestamp.now()是生成用户设备本地时间,完全由客户端控制,本身就达不到你防篡改的需求 - Firestore规则里的
request.time是请求到达服务端时的谷歌服务器时间,二者必然存在毫秒到秒级的差异,不可能全等,所以直接触发权限拒绝。
解决方案
你需要用Firestore提供的服务端时间戳占位符,它会在请求到达服务端时自动填充为服务器当前时间,和request.time完全一致,既可以通过规则校验,也能完全避免客户端篡改时间。
第一步:修改客户端写入逻辑
调整导入依赖和字段赋值:
// 把原来导入的Timestamp替换为serverTimestamp import { collection, addDoc, serverTimestamp } from "firebase/firestore"; const startSignal = async () => { try { const docRef = await addDoc(collection(db, "signals"), { active: true, // 替换原来的Timestamp.now(),使用服务端时间占位符 createdAt: serverTimestamp() }); console.log(docRef); } catch (e) { console.log("error"); console.log(e); } }
第二步:(可选)优化Firestore规则
你当前的规则已经可以正常通过写入请求,如果要更严谨,避免后续更新文档时被恶意修改createdAt字段,可以调整规则如下:
rules_version = '2'; service cloud.firestore { match /databases/{database}/documents { match /signals/{document=**} { allow create: if request.auth != null && request.resource.data.createdAt == request.time; allow update: if request.auth != null && request.resource.data.createdAt == resource.data.createdAt; allow read: if request.auth != null; } } }
规则含义:
- 新建文档时要求
createdAt必须等于服务端时间 - 更新文档时不允许修改
createdAt字段,必须和原有值一致
注意事项
因为服务端时间戳是请求到服务端才会赋值,所以在客户端拿到写入成功的回调之前,本地缓存的该文档createdAt字段会是null,前端渲染时需要做判空兼容,避免报错。
内容的提问来源于stack exchange,提问作者Anton Bogomolov
相关产品推荐
相关产品推荐

