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

自定义Claims与Firebase Firestore安全规则权限错误排查求助

问题解决:Firestore更新权限拒绝与Custom Claims配置错误

问题描述

完成前端开发后,搭建基于Custom Claims的后端安全规则体系,运行Callable Functions并重新登录后,尝试更新Firestore中属于自身的images集合文档时仍报错。规则设定为文档所有者或管理员可进行修改。

相关代码

前端提交代码

const onSubmit = async () => {
    const editRef = doc(db, `images/${imageID}`);
    try {
        await updateDoc(editRef, {
          aLabels: aLabels,
        });
      } catch (error) {
        console.log(error.message);
        toast.error("Something went wrong");
      }
}

Admin Claims配置代码

const functions = require("firebase-functions");
const admin = require("firebase-admin");

exports.setAdminClaims = functions.https.onRequest(async (req, res) => {
  const adminUIDs = [
    "pyqPlr3BT7LwzxBerxi1seqDrv6x"
  ];

  await Promise.all(
    adminUIDs.map((uid) =>
      admin.auth().setCustomUserClaims(uid, { admin: true })
    )
  );

  res.send("Done configuring rules");
});

Firestore安全规则

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
    allow read, write: if false; //line 5
    }
    match /images/{image} {
        allow read: if true;
        allow create: if isLoggedIn() //line 16
        allow update, delete: if isLoggedIn() && isOwner() || isAdmin() 
    }

    function isLoggedIn() {
        return request.auth.uid != null;
    }

    function isOwner() {
      return request.auth.uid == resource.data.user
    }

    function isAdmin() {
      return request.auth.token.role.admin == true
    }
}

错误信息

PERMISSION_DENIED: false for 'update' @ L5, evaluation error at
L16:32 for 'update' @ L16, false for 'update' @ L5, Property role is
undefined on object. for 'update' @ L16

问题分析与修复

1. 规则匹配顺序错误

Firestore规则是从上到下匹配,一旦命中就停止。现在全局规则match /{document=**}设置了全拒绝,这个规则会先于images集合的规则生效,直接拦掉所有操作。必须把全局规则移到所有特定集合规则的后面,作为默认兜底。

2. Admin权限判断字段不匹配

在isAdmin()函数里写了request.auth.token.role.admin,但实际在adminClaims代码中设置的Custom Claims是{ admin: true },根本没有role这个层级,所以会报“Property role is undefined”的错误。

3. 逻辑运算符优先级问题

isLoggedIn() && isOwner() || isAdmin()的逻辑有问题,因为&&优先级比||高,实际执行逻辑是(已登录且是所有者) 或 (是管理员),如果你的需求是“已登录,且(是所有者或管理员)”,必须加括号调整优先级。

修复后的安全规则

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    // 先定义images集合的规则
    match /images/{image} {
        allow read: if true;
        allow create: if isLoggedIn();
        allow update, delete: if isLoggedIn() && (isOwner() || isAdmin());
    }

    // 全局规则放在最后,作为默认拒绝
    match /{document=**} {
        allow read, write: if false;
    }

    function isLoggedIn() {
        return request.auth.uid != null;
    }

    function isOwner() {
      return request.auth.uid == resource.data.user;
    }

    function isAdmin() {
      // 对应Custom Claims里的admin字段
      return request.auth.token.admin == true;
    }
}

额外检查事项

  • 确认用户重新登录后,Custom Claims已生效:前端可以调用getAuth().currentUser.getIdTokenResult()查看token中的claims字段。
  • 确认images文档中的user字段确实是当前登录用户的UID,字段名要和规则里的resource.data.user完全一致。

内容的提问来源于stack exchange,提问作者Coolkid

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 13:16:26