我需要啥规则才能允许访问 Firestore 中的用户数据?

Posted

技术标签:

【中文标题】我需要啥规则才能允许访问 Firestore 中的用户数据?【英文标题】:What rule do I need to allow access to users data in Firestore?我需要什么规则才能允许访问 Firestore 中的用户数据? 【发布时间】:2022-01-20 19:47:09 【问题描述】:

我正在学习 Firestore,并构建了一个 Angular 应用程序。我正在使用 Firebase 身份验证,并且无法确定用于允许用户访问其数据的规则。因此,例如一个产品集合,其中每个产品都有一个 userId,这实际上是他们的电子邮件地址。

示例:

我的当前规则如下并且不起作用(我已经尝试了基于文档、*** 等我能想到的一切):

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
      
  

我所做的唯一有效的事情(即我拿回所有产品)是如果我做一个 match/document=**) 它将它向任何不是我想要的人开放。 :)

有什么想法吗?

编辑:如果有人想知道角度代码。同样,如果我设置规则以允许任何事情,我确实可以取回数据。如果我限制它,到目前为止我什么也得不到。所以,我知道代码有效(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();
  

【问题讨论】:

安全规则本身没有任何作用。请编辑您的问题,以包含与这些规则不符合您预期的代码。 您可以查看这些文档以编辑安全规则。 firebase.google.com/docs/firestore/security/rules-structurefirebase.google.com/docs/firestore/security/rules-conditions @FrankvanPuffelen 起初我不明白,因为这些规则是代码,但重读了您的评论,我发布了调用 firebase 的角度代码。 我的猜测是,当用户尚未登录时,您正在访问数据库。在访问数据库之前,尝试在代码中记录用户的 UID。 @FrankvanPuffelen 好的,我添加了登录用户电子邮件的日志记录,它运行良好。在请求所有数据之前按预期打印。 【参考方案1】:

我认为构建的安全规则存在一些问题。您可以参考Firestore security rules 了解更多关于编写规则和测试您的规则的信息,您可以参考documentation 提到的地方:

Cloud Firestore 提供了一个可用于测试的规则模拟器 你的规则集。您可以从Rules tab 访问模拟器 Firebase 控制台的 Cloud Firestore 部分。 规则模拟器让您模拟经过身份验证和 未经身份验证的读取、写入和删除。

a) 从 Firestore 数据库产品集合的屏幕截图中,文档 ID 似乎是一个自动生成的字母数字序列。因此,以下匹配规则将匹配 userEmail 和 userId 变量中的文档 ID(自动生成),而不是变量名称所暗示的用户电子邮件或用户 ID。

 match /users/userEmail
 match /products/userId

您当然可以创建文档 ID 以包含电子邮件地址而不是自动生成的序列,在这种情况下,上述匹配条件可能会按预期工作。

b) request.auth.uid.userEmail 的用法不正确。从用户的请求身份验证状态引用电子邮件的正确方法是"request.auth.token.email"。您可以阅读 Firestore 公共文档 -documentation1 和 documentation2 上的 request.auth &amp; resource variable references 以使用正确的语法。

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
    
  

【讨论】:

【参考方案2】:

我相信正确的语法是

        allow read, write: if request.auth.token.email == userId

有关详细信息,请参阅文档here。

【讨论】:

以上是关于我需要啥规则才能允许访问 Firestore 中的用户数据?的主要内容,如果未能解决你的问题,请参考以下文章

Firestore 安全规则 - 允许基于其父文档数据读取子集合

Firestore 规则:允许使用密码访问文档

访问 Firestore 规则中的父文档字段

如何根据设备平台为 Firestore 指定安全规则?

使用规则禁用 Firebase Cloud Firestore 中的查询集合

使用访问规则中的字段写入 Firestore 时缺少权限或权限不足