【问题标题】:Firebase firestore rules don't always work on webFirebase Firestore 规则并不总是适用于网络
【发布时间】:2020-10-30 12:48:49
【问题描述】:

考虑以下规则:

    match /triplogs/{anyDocument} {
      allow create: if request.auth != null;
      allow read, update, delete: if request.auth.uid == resource.data.userId;
    }

如果我用我的登录用户点击它,我会得到标准:

错误:FirebaseError:[code=permission-denied]:权限缺失或不足。

需要了解的几点:

  1. 我确实登录了,可以输出当前用户的UID,是正确的。
  2. 我可以通过移动版本走同样的路线,而且效果很好。
  3. 如果我删除 resource.data.userId 检查,并仅检查用户是否已通过身份验证(甚至硬编码 uid),它会起作用(因此该规则似乎得到了适当的检查)

模拟器说“资源”为空。我不明白资源对象怎么可能为空,也许是模拟器的问题?

任何帮助将不胜感激,在过去的几个小时里我已经解决了问题并在谷歌上搜索了,但没有成功。

有问题的查询:

// ... My firebase wrapper:
import { firebaseApp } from '../utils/firebase';
// ...

const collectionName = 'triplogs';

export const fetchTrips = async (filters?: Filter[]) => {
    let query;
    const ref = db?.collection(collectionName);
    const trips: TripLog[] = [];

    if (filters) {
        filters.forEach((filter) => {
            query = ref?.where(filter.field, filter.operator, filter.value);
        });
    }

    try {
        const obj = query || ref;
        console.log(firebaseApp()?.auth().currentUser?.uid); // <-- this is populated with my logged in UID, FWIW
        const docs = await obj?.get();
        docs?.forEach((doc) => {
            const data = doc.data() as TripLog;
            trips.push({
                ...data,
                id: doc.id
            });
        });

        return trips;
    } catch (err) {
        throw new Error(err);
    }
};

这是我尝试在模拟器中运行示例请求时的信息,违反了这些身份验证规则:

{
"path": "/databases/%28default%29/documents/triplogs/%7BanyDocument%7D"
"method": "get"
"auth": {
"uid": "5ompaySrXQcL9veWr3QlSujwlDS2"
"token": {
"sub": "5ompaySrXQcL9veWr3QlSujwlDS2"
"aud": "....omitted"
"firebase": {
"sign_in_provider": "google.com"
}
"email": "...omitted..."
"email_verified": true
"phone_number": ""
"name": "...."
}
}
"time": "2020-10-30T16:48:39.601Z"
}

sim中的错误是:

Error: simulator.rules line [32], column [58]. Null value error.

^^ 哪个是资源对象

如果我将身份验证规则更改为以下,那么我将取回数据

allow read, update, delete: if request.auth.uid != null;

类似的数据:

[{
    "createdAt": 1597527979495,
    "name": "Foo Bar Trip",
    "date": 1597527979495,
    "userId": "5ompaySrXQcL9veWr3QlSujwlDS2",
    "id": "FnH2E9WfDkpRHPLXxlDy"
}]

但只要我检查一个字段,“资源”对象就为空

allow read, update, delete: if request.auth.uid == resource.data.userId;

【问题讨论】:

  • 如果没有看到minimal code that reproduces the problem 的这些规则,任何人都很难说出发生了什么。由于您声称已登录,请确保代码在引发错误的调用之前记录活动用户,然后在您的问题中包含该代码及其输出。
  • 我们看不到客户端代码符合您的规则。您的问题应包含足够的信息,以便我们可以自行复制问题。
  • 对不起,我添加了一个代码示例。如果今晚晚些时候我能有时间,我会在某个地方创建一个 repro 应用程序。
  • 很高兴您找到了解决问题的方法。但是,实际的答案/解决方案不应编辑到您的问题中。一般来说,您应该edit澄清这个问题,但不要在其中包含答案。您应该使用用于解决问题的代码/解决方案创建自己的答案,然后接受它(系统可能需要 48 小时延迟才能这样做)。当您自己解决问题后,answering your own question is encouraged

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


【解决方案1】:

我会注意到您似乎正在查询一个集合,但您的规则似乎是为一个文档编写的......正如 here 所述,规则不是过滤器 - 它们不会分离集合中的单个文档。你在你的过滤器[array]中这样做吗?

【讨论】:

    【解决方案2】:

    不知道还会发生什么,但是您对过滤器数组的处理(我做了类似的事情)将不起作用 - 您正在替换每个循环上的查询,而不是扩展它。你可以试试

        query = ref;
        if (filters) {
            filters.forEach((filter) => {
                query = query?.where(filter.field, filter.operator, filter.value);
            });
        }
    

    扩展查询。

    另外,除非你的包装器做的比它显示的更多,你的行:

            const docs = await obj?.get();
    

    “获取”QuerySnapshot,而不是文档数组。你必须这样做

            const docs = await obj?.get().docs;
    

    获取实际文档的数组。

    最后,我们不知道(根据您上面的 sn-ps)用户 ID 字段是否存在于您的 Firestore 文档中

    【讨论】:

    • 我可以分享一个 json 的 firestore 文档来证明 useId 已被填充。否则代码可以正常工作(一旦我删除了提到的身份验证检查)。很好地调用了查询变量的替换(durrr...brain fart),谢谢。
    • 为了清楚起见,我添加了更多信息。
    • 问题:什么时候写的文件?是否有可能在模拟器中存在一个竞争条件,即最近编写的文档实际上还没有可供阅读?
    • 逻辑问题。在这种情况下,我有几秒到几年的记录。
    • 我刚刚连接“创建”一个新的旅行记录,这工作正常,那里有正确的 userId 和一切,但查询仍然不起作用。
    【解决方案3】:

    解决方案

    我想通了。我错误地认为我所做的查询是由身份验证规则自动过滤的(在本例中为 request.auth.id === userId)......但是到 firestore 的身份验证中间件并没有这样做。说得通。所以我只是添加了我的过滤器......像这样:

            fetchTrips([{
                field: 'userId',
                operator: '==',
                value: user.uid,
            }]);
    

    这有效并返回正确的结果。尝试正确更改用户 ID 也会引发身份验证错误。就是这样。

    【讨论】:

    • BWAHAHAHAH 我只是在输入同样的内容作为问题......
    • 厄运!感谢您的帮助。
    猜你喜欢
    • 2018-04-02
    • 1970-01-01
    • 2018-01-19
    • 2019-04-23
    • 2021-04-01
    • 2021-12-10
    • 2021-05-14
    • 1970-01-01
    • 2021-03-30
    相关资源
    最近更新 更多