Cloud Firestore安全规则playground生效但Angular调用报权限不足错误
Firestore安全规则测试通过但实际运行权限不足问题
问题描述
我正在优化Firestore数据库的安全规则,目前遇到问题:花了数小时调整规则尝试使其生效,却始终要么触发错误,要么拒绝访问。规则测试 playground 显示规则应当生效,但实际运行时不符合预期。
测试场景如下:使用路径为 /environment/STABLE/users/RMwv3mmP4RIOVqPOsa77 的用户,访问路径为 /environment/STABLE/route_sets/w3TBJrovQbgFPr2GFfug 的文档。该用户的db_role字段存储的字符串为ADMIN,目标route_sets文档包含名为_permissions_read的数组,值为TEST_NOTHING和ADMIN。
在规则测试 playground 中测试可以正常通过,但通过Angular应用调用时,收到错误:ERROR FirebaseError: Missing or insufficient permissions.。身份认证使用的是自定义Provider的Firebase Authentication,用户的uid对应users表的文档ID。Cloud Firestore的Rules页面中「monitor rules」标签的信息显示,访问route_set时当前规则触发了错误。
原始配置
原始安全规则
rules_version = "2"; service cloud.firestore { match /databases/{database}/documents { match /environment/{environment}/{collectionName}/{documentId} { allow read, write: if request.auth != null && collectionName == "route_sets" && checkPermissionRead(environment, collectionName, documentId); allow read: if request.auth != null && collectionName != "route_sets"; allow write, delete: if request.auth != null; function checkPermissionRead(environment, collectionName, documentId) { return get(/databases/$(database)/documents/environment/STABLE/users/$(request.auth.uid)).data.db_role in get(/databases/$(database)/documents/environment/$(environment)/$(collectionName)/$(documentId)).data._permissions_read; } } match /environment/STABLE/licenseholders/{document=**} { allow read: if true allow read, write: if request.auth != null; } match /environment/STABLE/users/{document=**} { allow read: if true allow read, write: if request.auth != null; } } }
原始Angular业务代码
import {Component, OnDestroy, OnInit} from '@angular/core'; import {AngularFirestore} from '@angular/fire/firestore'; import {AngularFireAuth} from '@angular/fire/auth'; @Component({ selector: 'app-example-security-rules', template: `<span *ngFor="let set of routeSets"></span>`, styles: [``], providers: [ ] }) export class ExampleSecurityRulesComponent implements OnInit { routeSets = []; constructor(private db: AngularFirestore, public afAuth: AngularFireAuth) { } ngOnInit() { this.afAuth.onAuthStateChanged(async (user) => { if (user) { this.db.collection<any>('environment/STABLE/route_sets').get().subscribe((d) => { d.forEach(docT => { this.routeSets.push({__document__key: docT.id, ...docT.data()}); }); }); } }); } }
修复后可正常运行的配置
调整后的安全规则
rules_version = "2"; service cloud.firestore { match /databases/{database}/documents { match /environment/{environment}/{collectionName}/{documentId} { allow read: if request.auth != null && collectionName != "route_sets"; allow write, delete: if request.auth != null; } match /environment/{environment}/route_sets/{document=**} { allow read, write: if request.auth != null && checkPermissionRead(environment); function checkPermissionRead(environment) { let user = get(/databases/$(database)/documents/environment/$(environment)/users/$(request.auth.uid)).data; return user.db_role in resource.data._permissions_read && user.licenseholder_id == resource.data.licenseholder_id; } } match /environment/STABLE/licenseholders/{document=**} { allow read: if true allow read, write: if request.auth != null; } match /environment/STABLE/users/{document=**} { allow read: if true allow read, write: if request.auth != null; } } }
调整后的Angular业务代码
this.db.collection<any>('environment/STABLE/route_sets').ref.where('licenseholder_id', '==', environment.licenseholder_id) .where('_permissions_read', 'array-contains', DatabaseRoles.ADMIN).get().then((d) => { d.forEach(docT => { this.routeSets.push({__document__key: docT.id, ...docT.data()}); }); });
内容的提问来源于stack exchange,提问作者Calvin
相关产品推荐
相关产品推荐

