我需要什么规则才能允许访问 Firestore 中的用户数据?
What rule do I need to allow access to users data in Firestore?
我正在学习 Firestore 并构建了一个 angular 应用程序。我正在使用 Firebase 身份验证,但无法确定用于允许用户访问其数据的规则。因此,例如一个产品集合,其中每个产品都有一个 userId,这实际上是他们的电子邮件地址。
示例:
我目前的规则如下,但没有用(我已经尝试了所有我能根据文档、Whosebug 等得出的结论):
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /users/{userEmail} {
allow read, write: if request.auth != null;
}
match /products/{userId}{
allow read, write: if request.auth.uid.userEmail == userId
}
}
}
我所做的唯一有效的事情(即我收回所有产品)是如果我做了一个匹配/{document=**),它向任何不是我想要的人开放。 :)
有什么想法吗?
编辑:以防有人对 angular 代码感到疑惑。同样,如果我将规则设置为允许我做的任何事情,我会取回数据。如果我限制它,到目前为止我什么也得不到。所以,我知道代码有效 (getAll) 因此一定是规则不正确。
编辑:我更新了代码,以便在从商店请求所有产品数据之前将用户电子邮件写入控制台。它成功地输出了用户的电子邮件。
import { Injectable } from '@angular/core';
import { AngularFirestore, AngularFirestoreCollection } from '@angular/fire/firestore';
import { AngularFireAuth } from '@angular/fire/auth';
import { Product } from '../models/product.model';
@Injectable({
providedIn: 'root'
})
export class ProductsService {
private dbPath = '/products';
productsRef: AngularFirestoreCollection<Product>;
constructor(public afAuth: AngularFireAuth, private db: AngularFirestore) {
this.productsRef = db.collection(this.dbPath);
}
getAll(): AngularFirestoreCollection<Product>{
this.afAuth.authState.subscribe(user => {
console.log('Dashboard: user', user);
if (user) {
let emailLower = user.email.toLowerCase();
console.log("Email: " + emailLower);
}
});
return this.productsRef;
}
create(product: Product): any {
return this.productsRef.add(product);
}
update(id: string, data: any): Promise<void>{
return this.productsRef.doc(id).update(data);
}
delete(id: string): Promise<void> {
return this.productsRef.doc(id).delete();
}
}
我认为构建的安全规则存在一些问题。您可以参考提到的Firestore security rules to learn more about writing rules and for testing your rules you can refer documentation:
Cloud Firestore provides a rules simulator that you can use to test
your ruleset. You can access the simulator from the Rules tab in the
Cloud Firestore section of the Firebase console.
The rules simulator lets you simulate authenticated and
unauthenticated reads, writes, and deletes.
a) 从 Firestore 数据库产品集合的屏幕截图来看,文档 ID 似乎是一个自动生成的字母数字序列。因此,下面的匹配规则将匹配 {userEmail} 和 {userId} 变量中的文档 ID(自动生成),而不是变量名称所暗示的用户电子邮件或用户 ID。
match /users/{userEmail}
match /products/{userId}
您当然可以创建包含电子邮件地址的文档 ID,而不是自动生成的序列,在这种情况下,上述匹配条件可能会按预期工作。
b) request.auth.uid.userEmail
的用法不正确。从用户请求身份验证状态引用电子邮件的正确方法是 "request.auth.token.email"
。您可以阅读 Firestore public 文档中的 request.auth & resource variable references
-documentation1 & documentation2 以使用正确的语法。
c) 以下是对安全规则所做的一些更正。这应该有效。
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /users/{userDocId} {
allow read, write: if request.auth != null;
}
match /products/{productDocId}{
allow read, write: if request.auth.token.email == resource.data.userId
}
}
}
我认为正确的语法是
allow read, write: if request.auth.token.email == userId
请参阅文档here了解更多详情。
我正在学习 Firestore 并构建了一个 angular 应用程序。我正在使用 Firebase 身份验证,但无法确定用于允许用户访问其数据的规则。因此,例如一个产品集合,其中每个产品都有一个 userId,这实际上是他们的电子邮件地址。
示例:
我目前的规则如下,但没有用(我已经尝试了所有我能根据文档、Whosebug 等得出的结论):
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /users/{userEmail} {
allow read, write: if request.auth != null;
}
match /products/{userId}{
allow read, write: if request.auth.uid.userEmail == userId
}
}
}
我所做的唯一有效的事情(即我收回所有产品)是如果我做了一个匹配/{document=**),它向任何不是我想要的人开放。 :)
有什么想法吗?
编辑:以防有人对 angular 代码感到疑惑。同样,如果我将规则设置为允许我做的任何事情,我会取回数据。如果我限制它,到目前为止我什么也得不到。所以,我知道代码有效 (getAll) 因此一定是规则不正确。
编辑:我更新了代码,以便在从商店请求所有产品数据之前将用户电子邮件写入控制台。它成功地输出了用户的电子邮件。
import { Injectable } from '@angular/core';
import { AngularFirestore, AngularFirestoreCollection } from '@angular/fire/firestore';
import { AngularFireAuth } from '@angular/fire/auth';
import { Product } from '../models/product.model';
@Injectable({
providedIn: 'root'
})
export class ProductsService {
private dbPath = '/products';
productsRef: AngularFirestoreCollection<Product>;
constructor(public afAuth: AngularFireAuth, private db: AngularFirestore) {
this.productsRef = db.collection(this.dbPath);
}
getAll(): AngularFirestoreCollection<Product>{
this.afAuth.authState.subscribe(user => {
console.log('Dashboard: user', user);
if (user) {
let emailLower = user.email.toLowerCase();
console.log("Email: " + emailLower);
}
});
return this.productsRef;
}
create(product: Product): any {
return this.productsRef.add(product);
}
update(id: string, data: any): Promise<void>{
return this.productsRef.doc(id).update(data);
}
delete(id: string): Promise<void> {
return this.productsRef.doc(id).delete();
}
}
我认为构建的安全规则存在一些问题。您可以参考提到的Firestore security rules to learn more about writing rules and for testing your rules you can refer documentation:
Cloud Firestore provides a rules simulator that you can use to test your ruleset. You can access the simulator from the Rules tab in the Cloud Firestore section of the Firebase console. The rules simulator lets you simulate authenticated and unauthenticated reads, writes, and deletes.
a) 从 Firestore 数据库产品集合的屏幕截图来看,文档 ID 似乎是一个自动生成的字母数字序列。因此,下面的匹配规则将匹配 {userEmail} 和 {userId} 变量中的文档 ID(自动生成),而不是变量名称所暗示的用户电子邮件或用户 ID。
match /users/{userEmail}
match /products/{userId}
您当然可以创建包含电子邮件地址的文档 ID,而不是自动生成的序列,在这种情况下,上述匹配条件可能会按预期工作。
b) request.auth.uid.userEmail
的用法不正确。从用户请求身份验证状态引用电子邮件的正确方法是 "request.auth.token.email"
。您可以阅读 Firestore public 文档中的 request.auth & resource variable references
-documentation1 & documentation2 以使用正确的语法。
c) 以下是对安全规则所做的一些更正。这应该有效。
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /users/{userDocId} {
allow read, write: if request.auth != null;
}
match /products/{productDocId}{
allow read, write: if request.auth.token.email == resource.data.userId
}
}
}
我认为正确的语法是
allow read, write: if request.auth.token.email == userId
请参阅文档here了解更多详情。