Firestore安全规则权限不足问题排查(Angularfire2环境)
嘿,我来帮你捋清楚这个Firestore安全规则的权限问题!结合你用的angularfire2: 5.0.0-rc.6、firebase: 4.10.1这些旧版本,还有你要实现的「仅允许用户获取匹配自身UID的文档」需求,咱们一步步排查:
一、先确认身份验证基础是否靠谱
首先得确保你的Angular应用已经正确完成用户登录,Firestore规则里的request.auth.uid能拿到有效值。你可以先写个测试规则验证:
rules_version = '1'; // 注意:你用的firebase 4.x版本得用rules_version '1',v2是后来版本才引入的 service cloud.firestore { match /databases/{database}/documents { match /{document=**} { allow read, write: if request.auth != null; } } }
如果这个规则下请求正常,说明身份验证没问题,问题出在用户ID匹配的规则逻辑;如果还是报错,那先去排查AngularFire的登录逻辑,确保AngularFireAuth已经正确初始化,用户确实处于登录状态。
二、常见的规则与查询不匹配场景及修复
假设你的目标集合是users,这里分两种常见场景,规则写法和查询逻辑必须严格对应,不然就会触发权限报错:
1. 文档ID直接等于用户UID
如果你的users集合里,每个文档的ID就是用户的UID,那规则得这么写:
rules_version = '1'; service cloud.firestore { match /databases/{database}/documents { match /users/{userId} { allow read, write: if request.auth.uid == userId; } } }
对应的AngularFire查询要直接获取单个文档:
// 正确写法:拿到当前用户后直接取对应ID的文档 this.afAuth.authState.subscribe(user => { if (user) { this.userDoc = this.afs.doc(`users/${user.uid}`); this.user$ = this.userDoc.valueChanges(); } });
要是你写的查询是collection('users').where('uid', '==', user.uid),但规则是匹配文档ID,那肯定不匹配——规则要求文档ID等于UID,而你查的是字段,逻辑对不上,自然报错。
2. 文档内有userId字段(文档ID不是UID)
如果文档里存了userId字段用来关联用户,那规则要验证这个字段的值:
rules_version = '1'; service cloud.firestore { match /databases/{database}/documents { match /users/{docId} { // 读取权限:已登录+文档userId等于当前用户UID allow read: if request.auth != null && request.auth.uid == resource.data.userId; // 创建文档时:必须保证写入的userId和当前用户一致 allow create: if request.auth != null && request.auth.uid == request.resource.data.userId; // 更新/删除同理,要验证文档属于当前用户 allow update, delete: if request.auth != null && request.auth.uid == resource.data.userId; } } }
⚠️ 重点:Firestore的规则是提前检查查询是否符合限制,不是事后过滤结果!所以你的查询必须带where子句匹配userId,不能直接查整个集合:
// 正确写法:必须带上where条件,和规则逻辑对应 this.afAuth.authState.subscribe(user => { if (user) { this.user$ = this.afs.collection('users', ref => ref.where('userId', '==', user.uid)).valueChanges(); } });
要是你没带这个where条件,哪怕实际返回的只有用户自己的文档,规则也会直接拒绝请求。
三、旧版本兼容性的坑
你用的这些版本比较老,可能存在一些小问题:
- 一定要确保查询是在用户登录后才执行的,别在
authState还没返回用户信息时就发起请求,不然request.auth会是null,直接触发权限错误 - 旧版本里
request.resource.data(创建文档时的写入数据)的处理可能有细微差异,创建文档时要确认写入的userId确实和当前用户UID完全一致
四、用模拟器快速调试规则
Firebase控制台的规则模拟器是个好工具,能帮你快速定位问题:
- 打开Firebase控制台,进入Firestore的「规则」页面
- 点击「模拟器」,选择要测试的操作(读取/写入)
- 输入集合路径、文档ID(如果是单文档),模拟已登录用户(填入测试UID)
- 运行测试,模拟器会告诉你哪一步规则不通过,一目了然
五、完整可工作的规则示例(针对文档带userId字段的场景)
给你贴个完整的规则,你可以直接参考调整:
rules_version = '1'; service cloud.firestore { match /databases/{database}/documents { match /users/{userDoc} { allow read: if request.auth != null && request.auth.uid == resource.data.userId; allow create: if request.auth != null && request.auth.uid == request.resource.data.userId; allow update, delete: if request.auth != null && request.auth.uid == resource.data.userId; } } }
最后再检查几个细节
- 确认查询代码里的
user.uid不为空,且和文档里的userId(或文档ID)完全一致——UID是大小写敏感的,别写错大小写 - 规则里用的是
request.auth.uid,别写成request.auth.id,Firestore规则里一直是uid - 如果是批量操作或者复合查询,要确保每个条件都符合规则的限制
内容的提问来源于stack exchange,提问作者Shanky

