如何在Cloud Firestore安全规则中仅允许负值更新?
问题:Cloud Firestore安全规则限制积分仅可扣除
我使用React、RTK Query和Cloud Firestore开发客户端应用,用户可积累积分用于购买商品,但订单环节的积分扣除存在安全漏洞——当前的Firestore安全规则允许用户修改自己的积分,但无法阻止用户给自己增加积分。
当前安全规则代码:
function isOwner(userId){ return request.auth.uid == userId; } function isSignedIn() { return request.auth != null; } match /users/{userId} { allow update: if request.resource.data.diff(resource.data).changedKeys().hasOnly(["points"]) && isSignedIn() && isOwner(userId); }
对应的RTK Query mutation代码:
userPayment: builder.mutation({ async queryFn(data) { try { const docRef = doc(db, "users", data.userId); await updateDoc(docRef, { points: increment(-data.totalPrice) }) return {data: "payment successful"} } catch (err) { return {error: err} } }, invalidatesTags: ["UserData"] }),
解决方案
修改安全规则,仅允许积分减少
你可以通过对比更新前后的积分值,在安全规则中限制只能扣除积分(即新积分≤旧积分)。修改后的规则如下:
function isOwner(userId){ return request.auth.uid == userId; } function isSignedIn() { return request.auth != null; } match /users/{userId} { allow update: if request.resource.data.diff(resource.data).changedKeys().hasOnly(["points"]) && isSignedIn() && isOwner(userId) // 限制更新后的积分不大于原有积分,仅允许扣除或保持不变 && request.resource.data.points <= resource.data.points; }
可选优化:防止积分变为负数
如果需要避免用户积分被扣至负数,可以额外添加一个条件:
&& request.resource.data.points >= 0
这样修改后,即便客户端被篡改发送增加积分的请求,Firestore安全规则也会直接拒绝操作,从根源上保证积分扣除的安全性——仅依赖前端RTK Query的逻辑确实不够,必须通过后端安全规则加固。
内容的提问来源于stack exchange,提问作者Navih
相关产品推荐
相关产品推荐

