You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Firebase Auth规则合规:客户端写入Firestore权限失效及安全实现咨询

解决方案

1. 先修复安全规则的语法错误

你提供的安全规则缺少闭合大括号,这会直接导致规则无法正常生效。另外,为了进一步提升安全性,我们需要限制写入操作只能是递增计数,防止用户篡改字段或设置任意数值:

service cloud.firestore {
  match /databases/{database}/documents {
    match /actions/{uid} {
      // 仅允许认证用户操作自己的文档
      allow read, write: if request.auth.uid == uid;
      // 额外限制写入只能是递增指定动作的计数
      allow update: if request.resource.data.keys().size() == 1 &&
                    request.resource.data[request.resource.data.keys().first()] is int &&
                    request.resource.data[request.resource.data.keys().first()] == resource.data.get(request.resource.data.keys().first(), 0) + 1;
    }
  }
}

2. 修正客户端代码的核心问题

你的代码存在两个关键隐患:

  • 依赖外部传入的user参数,恶意用户可伪造该参数传入任意UID
  • 写入字段固定为action,若action是动作类型(比如"click""scroll"),无法区分不同动作的计数

修正后的代码直接从Firebase Auth获取当前登录用户的UID,彻底避免伪造风险:

import { doc, updateDoc, increment } from "firebase/firestore";
import { getAuth } from "firebase/auth";

export const updateUserWithAction = async (action) => {
  const auth = getAuth();
  const currentUser = auth.currentUser;
  
  // 校验用户登录状态
  if (!currentUser) {
    throw new Error("用户未登录,无法记录操作");
  }

  const userDocRef = doc(db, 'actions', currentUser.uid);
  // 用动态字段名记录对应动作的计数
  await updateDoc(userDocRef, {
    [action]: increment(1)
  });
};

3. 关键安全逻辑说明

  • Firebase Auth认证状态自动同步:只要客户端完成Firebase Auth登录,Firestore安全规则中的request.auth.uid会自动获取当前用户的真实UID,客户端无法篡改该对象——因为它由Firebase后台验证生成。
  • 杜绝客户端传入用户信息:直接使用getAuth().currentUser获取用户数据,彻底避免恶意用户伪造UID的可能。
  • 限制写入操作类型:安全规则中额外校验写入只能是递增操作,防止用户通过修改客户端代码直接设置任意计数(比如把数值改成1000)。

4. 补充:首次操作的文档创建

如果用户第一次执行操作时/actions/{uid}文档不存在,updateDoc会自动创建该文档。若你需要强制文档存在才允许更新,可改用setDoc并设置merge: true,效果与updateDoc一致。

内容的提问来源于stack exchange,提问作者Mark C.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 17:35:26