Firestore安全规则:允许单条读取,列表查询需匹配指定键
没问题!针对你的需求,Firestore安全规则完全可以直接校验查询的where()条件,不一定非要嵌套集合——两种方案各有适用场景,我给你详细说说:
方案1:通过安全规则检查查询的where()条件
Firestore的安全规则提供了request.query对象,能直接获取客户端发起查询时的过滤条件。针对你“仅允许列出特定看板下项目”的需求,规则可以这么写:
rules_version = '2'; service cloud.firestore { match /databases/{database}/documents { // 允许任意单文档的get请求 match /projects/{projectId} { allow get: if true; // 仅当查询包含boardId的相等过滤,且与文档自身的boardId匹配时允许list allow list: if request.query.where('boardId', '==', resource.data.boardId); } } }
关键说明:
request.query.where('boardId', '==', resource.data.boardId)会校验客户端是否添加了where('boardId', '==', 目标看板ID)的条件,并且这个条件的值和文档本身的boardId字段一致——这样就能确保用户只能拉取指定看板下的项目,无法发起无过滤的全量list请求。- 如果你还需要验证用户是否有权访问该看板,可以叠加额外逻辑,比如检查看板是否存在、用户是否是看板成员:
allow list: if request.query.where('boardId', '==', resource.data.boardId) // 校验看板存在 && exists(/databases/$(database)/documents/boards/$(request.query.where('boardId', '==').value)) // 校验用户是看板成员 && get(/databases/$(database)/documents/boards/$(request.query.where('boardId', '==').value)).data.members.has(request.auth.uid);
方案2:将projects嵌套在boards集合下
如果你的业务逻辑中,项目永远属于单个看板,不会跨看板存在,把projects集合嵌套到boards下(路径为/boards/{boardId}/projects/{projectId})会是更简洁的方案,此时安全规则的逻辑会更直观:
rules_version = '2'; service cloud.firestore { match /databases/{database}/documents { match /boards/{boardId}/projects/{projectId} { allow get: if true; // 路径已经限定了看板范围,list自然只能获取该看板下的项目 allow list: if true; // 可选:添加看板权限校验 // allow list: if get(/databases/$(database)/documents/boards/$(boardId)).data.members.has(request.auth.uid); } } }
这种方案的优势:
- 路径本身就做了范围限制,不用依赖客户端的查询条件,避免因为客户端漏加
where导致请求被拒。 - 数据结构更贴合业务关系,查询时直接通过看板路径获取项目,逻辑更清晰。
方案选择建议
- 如果项目可能属于多个看板,或者需要灵活组合查询条件,优先选方案1。
- 如果项目严格绑定单个看板,业务逻辑固定,优先选方案2,更可靠简洁。
内容的提问来源于stack exchange,提问作者basil
相关产品推荐
相关产品推荐

