【问题标题】:Firestore retrieve multiple documents security rulesFirestore 检索多个文档安全规则
【发布时间】:2020-07-04 16:14:37
【问题描述】:

我的应用程序中有一个 recyclerview,它通过 get 检索集合中的所有文档。每个文档都包含创建它的人的 uid。我想实现一个安全规则,在该规则中,您只检索与所有者的 uid 匹配的文档。它看起来很简单,但我无法让它工作。

数据库有这样的结构

cars
|
|-documentA
|-documentB
|-documentC

每个文档:

documentA
|
|
|-fieldA: aaa
|-fieldB: bbb
|-userId: aklsjdaosjfpasf

firestore 的安全规则

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /{cars=**}/{carId}  {
    allow read: if request.auth.uid == resource.data.userId;
    allow write: if request.auth.uid != null;
  }
  }
}

编辑 查询:

query = firestore.collection("cars").limit(10L)

用于查询 recyclerview 的 Firestore 适配器

public abstract class FirestoreAdapter<VH extends RecyclerView.ViewHolder>
        extends RecyclerView.Adapter<VH> {

    private static final String TAG = "Firestore Adapter";

    private Query mQuery;
    private ListenerRegistration mRegistration;

    private ArrayList<DocumentSnapshot> mSnapshots = new ArrayList<>();

    public FirestoreAdapter(Query query) {
        mQuery = query;
    }

    public void startListening() {
        // TODO(developer): Implement
    }

    public void stopListening() {
        if (mRegistration != null) {
            mRegistration.remove();
            mRegistration = null;
        }

        mSnapshots.clear();
        notifyDataSetChanged();
    }

    public void setQuery(Query query) {
        // Stop listening
        stopListening();

        // Clear existing data
        mSnapshots.clear();
        notifyDataSetChanged();

        // Listen to new query
        mQuery = query;
        startListening();
    }

    @Override
    public int getItemCount() {
        return mSnapshots.size();
    }

    protected DocumentSnapshot getSnapshot(int index) {
        return mSnapshots.get(index);
    }

    protected void onError(FirebaseFirestoreException e) {};

    protected void onDataChanged() {}
}

【问题讨论】:

  • 究竟是什么不符合您的安全规则?同样只允许读取匹配的用户但允许写入所有经过身份验证的用户似乎是错误的
  • 我无法从我的 recyclerview 中检索任何内容,它给了我一个错误,我没有足够的权限。允许所有用户在应用程序中进行身份验证的想法是因为每个人都可以注册汽车,但只有车主才能看到。
  • 这种做法是错误的,如果你允许某人写一个文件,他们就可以阅读它。您可能想使用allow create 而不是allow write
  • 好的,有道理。我就是这样改变的。了解创建和写入的区别。
  • 您能否在问题中添加用于获取数据的查询?

标签: firebase google-cloud-firestore firebase-security


【解决方案1】:

根据 cmets,我认为这可能是解决方案。根据 OP,所有用户都应该能够注册汽车,但只有创建汽车的用户才能看到它。

在这种情况下,正确的权限如下所示:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /cars/{carId}  {
      allow read, write: if request.auth.uid == resource.data.userId;
      allow create: if request.auth.uid != null;
    }
  }
}

对于第 2 版之前的规则:

权限URL也有问题,你可以使用下面的语法来匹配一个集合中的所有文档:/cars/{documemts=**}/,但是你的路径/{cars=**}/{carId}是无效的,因此这个规则永远不会对你的查询强制执行.

路径/cars/{carId} 将引用集合“cars”中的任何文档,将文档的名称存储为“carId”。

【讨论】:

  • 感谢您的回复。仍然没有得到任何结果并得到同样的错误,访问被拒绝。
  • 能否将回收站视图代码添加到您的问题中?
  • @Max 请注意,使用版本 2 的安全规则,您可以在 匹配语句中的任何位置 放置通配符(请参阅 firebase.google.com/docs/firestore/security/…)。所以你对match /cars/{carId}的评论(它“将引用集合'cars'中的任何文档,将文档的名称存储为'carId'。”)是正确的,但OP规则在技术上并没有错。
【解决方案2】:

您必须注意,安全规则不是过滤器,如documentation 中所述:

一旦您保护了您的数据并开始编写查询,请记住 安全规则不是过滤器。 您不能为 集合中的所有文档并期望 Cloud Firestore 仅返回当前客户端有权访问的文档 访问

query = firestore.collection("cars").limit(10L)

您的查询独立于userId,因此出现了问题。

您需要使用whereEqualTo() 调整您的查询,如下所示:

//get the value of uid
query = firestore.collection("cars").whereEqualTo("userId", uid).limit(10L)

【讨论】:

  • 这是一个很好的观点,即使设置了正确的权限,对该集合中所有文档的查询仍然会失败,因为您将查询您没有任何读取权限的文档跨度>
猜你喜欢
  • 2020-06-19
  • 2018-06-15
  • 2019-12-02
  • 1970-01-01
  • 2019-03-03
  • 2019-02-01
  • 2021-10-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多