【问题标题】:Firebase Cloud Firestore rules / permissions issueFirebase Cloud Firestore 规则/权限问题
【发布时间】:2021-06-13 11:07:58
【问题描述】:

我正在尝试设置权限,以便具有给定电子邮件地址的用户只能阅读具有匹配 docId 的文档。

这是文档集合:

/cats/a@test.com
/cats/b@test.com
/cats/c@test.com

以下内容在“Rules Playground”中完美运行,但最终在我的 Angular 应用程序中始终没有返回任何内容。

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {

    match /cats/{catDocId} {
      allow read: if request.auth.token.email.lower() == catDocId;
      allow write: if false;
    }

  }
}

这是应用程序代码:

myPage.component.ts:

import { AngularFireAuth } from '@angular/fire/auth';
import { AngularFirestore } from '@angular/fire/firestore';
import { Observable } from 'rxjs';

// ...

cats: Observable<any[]>;

// ...

ngOnInit(): void {
    this.afAuth.authState.subscribe(user => {
        this.cats = this.firestore.collection('cats').valueChanges();
    });
}

myPage.component.html:

<ul>
    <li class="text" *ngFor="let cat of cats | async">
        {{cat.name}}, {{cat.color}}, {{cat.favoriteFood}}
    </li>
</ul>

有什么想法会出错吗?谢谢。

【问题讨论】:

  • 明显问题:您的用户登录了吗?
  • 另外,您能分享您的查询吗?确实需要注意的是安全规则不是过滤器,见firebase.google.com/docs/firestore/security/…
  • 是的,用户已登录,我已编辑问题以包含 Angular 代码。谢谢
  • 看来我正在尝试将规则用作过滤器。有没有一种简单的方法可以根据用户的令牌数据(即他们的电子邮件地址)授予对单个文档的读取权限?

标签: javascript angular google-cloud-firestore firebase-authentication firebase-security


【解决方案1】:

来自您的评论:

看来我正在尝试将规则用作过滤器。有没有简单的 基于用户令牌授予对单个文档的读取访问权限的方法 数据,即他们的电子邮件地址?

您只需要使用User 对象即可获取用户的电子邮件。我并不真正精通angularfire,但以下代码(来自 angularfire doc on Authentication)显示了如何获取 displayName 属性。您应该对 email 属性执行相同的操作。然后你应该直接查询文档,正如here 解释的那样,因为你有整个DocumentReference

import { Component } from '@angular/core';
import { AngularFireAuth } from '@angular/fire/auth';
import firebase from 'firebase/app';

@Component({
  selector: 'app-root',
  template: `
    <div *ngIf="auth.user | async as user; else showLogin">
      <h1>Hello {{ user.displayName }}!</h1>
      <button (click)="logout()">Logout</button>
    </div>
    <ng-template #showLogin>
      <p>Please login.</p>
      <button (click)="login()">Login with Google</button>
    </ng-template>
  `,
})
export class AppComponent {
  constructor(public auth: AngularFireAuth) {
  }
  login() {
    this.auth.signInWithPopup(new firebase.auth.GoogleAuthProvider());
  }
  logout() {
    this.auth.signOut();
  }
}

【讨论】:

  • 谢谢雷诺。我可以毫无问题地查找用户的电子邮件。这是否意味着我应该将我的 Cloud Firestore 权限设置为“允许读取:如果 request.auth != null;” (即:如果用户已登录,则允许读取)然后在 Angular 端过滤结果?我只是想在 Firebase 数据库中尽可能安全
  • allow read: if request.auth.token.email.lower() == catDocId; 是必要的(它可以防止其他用户阅读用户的文档)并且它也足够 IMO,因为如果用户未登录,request.auth 将为空。
  • 所以要完整,不需要“在 Angular 端过滤结果”。只需获取一个且只有一个文档,即具有/cats/a@test.com 路径的文档,并像您在问题中所做的那样保护它。
  • 但问题仍然是allow read: if request.auth.token.email.lower() == catDocId; 仅适用于规则操场,它在实际的 Angular 应用程序中返回零文档:(
  • 您确定您正确获取了一份文档吗?你不应该query the collection,而是fetch one specific doc based on its path/reference
猜你喜欢
  • 1970-01-01
  • 2019-08-20
  • 2021-06-21
  • 1970-01-01
  • 2017-03-11
  • 1970-01-01
  • 2020-10-17
  • 2019-12-15
  • 2018-06-21
相关资源
最近更新 更多