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

Firestore权限配置:仅允许聊天参与用户读写消息

问题描述

接手的项目采用Firestore数据模型,数据路径为/Chat/{chatId}/messages/{messageId},数据结构如下:

/Chat/{chatId}
{
  users: ["24","51"]
  messages: [ // 子集合
    {message:"...", sender: 24, time:"...", users: ["24","51"]},
  ]
}

通过Flutter的StreamBuilder读取聊天消息:

StreamBuilder<QuerySnapshot>(
  stream: FirebaseFirestore.instance
             .collection("Chat")
             .doc(chatID.toString())
             .collection("messages")
             .orderBy("time", descending: false)
             .snapshots(),
)

需要实现仅聊天参与者可读写消息,但当前配置的规则触发权限错误:Chat/1103/messages failed: Missing or insufficient permissions.

当前规则:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {  
    match /Chat/{chatId}{
      allow read: if "24" in resource.data.users // 24测试后将替换为request.auth.uid
      allow write
      
      match /messages/{messageId}{
        allow read: if "24" in resource.data.users // 24测试后将替换为request.auth.uid
        allow write
        }
    }
  }
}
正确的Firestore安全规则实现

问题分析

  1. 当前messages集合的读取判断依赖resource.data.users,但Firestore查询时会校验整个集合的权限,这种单文档级别的判断无法通过批量查询的权限验证。
  2. allow write未添加任何权限限制,存在越权操作风险。
  3. 固定ID"24"未替换为动态的request.auth.uid,无法适配真实多用户场景。

修正后的规则

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {  
    // 验证用户已完成Firebase认证
    function isAuthenticated() {
      return request.auth != null;
    }
    
    // 验证用户是当前聊天的参与者
    function isChatParticipant(chatDoc) {
      return request.auth.uid in chatDoc.data.users;
    }

    match /Chat/{chatId} {
      // 仅允许聊天参与者读写Chat主文档
      allow read, write: if isAuthenticated() && isChatParticipant(resource);

      match /messages/{messageId} {
        // 引用父级Chat文档的users数组验证权限,适配批量查询
        allow read: if isAuthenticated() && isChatParticipant(get(/databases/$(database)/documents/Chat/$(chatId)));
        
        // 写入消息时,确保发送者是聊天参与者且身份合法
        allow write: if isAuthenticated() && 
                      isChatParticipant(get(/databases/$(database)/documents/Chat/$(chatId))) &&
                      request.resource.data.sender == request.auth.uid;
      }
    }
  }
}

规则说明

  1. isAuthenticated():拦截未登录用户的所有操作,确保只有已认证用户能访问聊天数据。
  2. isChatParticipant():复用权限判断逻辑,通过父级Chat文档的users数组验证身份,无需在每条消息中重复存储参与者列表(若已存储也可改用resource.data.users,但父文档引用更高效)。
  3. messages集合权限:
    • 读取:验证用户身份及聊天参与者身份,满足批量查询的权限校验要求,适配你的StreamBuilder查询场景。
    • 写入:除验证参与者身份外,强制消息的sender字段与当前用户ID一致,防止伪造消息发送者。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 04:05:19