【发布时间】:2021-11-22 07:11:27
【问题描述】:
我正在尝试提高 Firestore 数据库的安全性,但我对此感到绝望。我已经尝试编辑它几个小时以尝试它是否可以工作,但它不断出错或拒绝访问。规则游乐场表明它应该工作..但它没有。
我正在尝试使用用户 /environment/STABLE/users/RMwv3mmP4RIOVqPOsa77 访问 /environment/STABLE/route_sets/w3TBJrovQbgFPr2GFfug。用户有一个名为 db_role 的字段,其中包含字符串 ADMIN。 route_sets 中的文档包含一个名为 _permissions_read 的数组,其值为 TEST_NOTHING 和 ADMIN。
使用规则游乐场测试它可以工作,但是当我通过我的 Angular 应用程序尝试它时,我得到“错误 FirebaseError:缺少或不足的权限。”。对于身份验证,我将 Firebase 身份验证与自定义提供程序一起使用,uid 是用户表中的文档 ID。
Cloud Firestore 上“监控规则”选项卡上的信息 -> 规则似乎表明当前规则(如下所示)在尝试访问 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;
}
}
}
角度
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()});
});
});
【问题讨论】:
-
请编辑您的问题以包含可以解决问题的最少代码,而不是描述您的代码。如果在该代码中显示它满足安全规则,它也会有所帮助(因此:显示
firebase.auth().currentUser具有值 -
嘿弗兰克,感谢您的回复。我添加了最少的代码,这有帮助吗?
-
谢谢,这有帮助,虽然我还不知道出了什么问题。如果禁用
checkPermissionRead调用,读取是否成功? -
是的,在没有函数调用的情况下读取成功。 (编辑规则:pastebin.com/hP0xEsUb)
标签: javascript firebase google-cloud-firestore firebase-security