如何确保Firestore安全规则仅接受Firestore Timestamp而非JavaScript Date
问题解决:Firestore规则未阻止JavaScript Date类型输入
核心问题分析
字段名称不匹配
你的Firestore规则中校验的字段是creationDate,但测试代码里传入的字段是dateCreated——规则根本没有对目标字段执行校验逻辑,所以请求直接通过了。Firebase SDK自动转换机制
即使修正了字段名,Firebase JS SDK在调用setDoc时,会自动把JavaScript的Date对象转换为Firestore的Timestamp类型。到达Firestore服务器的数据已经是合法的timestamp类型,规则中的creationDate is timestamp判断会认为输入合法,导致你的测试无法触发预期的失败。
具体解决方案
1. 统一字段名称
首先确保规则和测试代码中的字段名完全一致,以下是两种修正方式:
方式一:修正Firestore规则
match /users/{userId} { allow create: if (request.resource.data.dateCreated != null && request.resource.data.dateCreated is timestamp) }
方式二:修正测试代码中的字段名
将测试里的dateCreated改为creationDate,和规则保持统一。
2. 构造正确的非法输入测试用例
如果你的目标是验证规则能阻止非Timestamp类型的日期输入(比如字符串日期、自定义对象),需要构造不会被SDK自动转换的非法输入:
it('Fails if dateCreated is not a Firestore timestamp', async () => { // Arrange const authedUser = testEnv.authenticatedContext(myId); const db = authedUser.firestore(); const docRef = doc(db, 'users', myId); // 构造非法输入:字符串格式的日期(不会被SDK转换为Timestamp) const docData = { dateCreated: "2024-01-01" }; // Act & Assert await assertFails(setDoc(docRef, docData)); });
3. 强制使用服务器生成时间戳(可选)
如果你的真实需求是防止客户端自行设置日期,必须由服务器生成,可以修改规则要求日期等于请求时间:
match /users/{userId} { allow create: if (request.resource.data.dateCreated == request.time) }
此时客户端需要使用serverTimestamp()来设置字段:
const docData = { dateCreated: firebase.firestore.FieldValue.serverTimestamp() };
内容的提问来源于stack exchange,提问作者Reagankm
相关产品推荐
相关产品推荐

