【问题标题】:Firestore Security Rules: Can't understand why certain rules do/don't workFirestore 安全规则:无法理解为什么某些规则有效/无效
【发布时间】:2018-08-29 12:05:09
【问题描述】:

我的 firestore 数据库的结构是“联赛”是顶级集合,每个联赛都包含一个以每个批准的用户 ID 命名的字段(带有一个数字值)。

每个联盟还有一个以每个批准的用户 ID 命名的文档子集合“用户”。

 

这是一个示例 firestore 查询:

FirebaseAuth mAuth = FirebaseAuth.getInstance();

// userId = ABCDEF123 for this example
String userId = mAuth.getCurrentUser().getUid();

FirebaseFirestore firestore = FirebaseFirestore.getInstance();
firestore.collection("leagues").whereLessThan(userId, 99).get();

 

谁能告诉我为什么这条规则有效:

match /leagues/{league} {
    allow read, write: if resource.data.ABCDEF123 != null;

但不是这个:

match /leagues/{league} {
    allow read, write: if resource.data.request.auth.uid != null;

 

另外,为什么这条规则有效:

//"ZYXWV987" is an example of a league the user is in
match /leagues/{league} {
    allow read, write: if exists(/databases/$(database)/documents/leagues/$('ZYXWV987')/users/$(request.auth.uid));

但不是这个:

match /leagues/{league} {
    allow read, write: if exists(/databases/$(database)/documents/leagues/$(league)/users/$(request.auth.uid));

 

我得到的错误是“com.google.firebase.firestore.FirebaseFirestoreException: PERMISSION_DENIED: Missing or enough permissions”

 

我希望了解这些规则的工作原理,以及如何为我的数据库实施适当的规则!

编辑:

我现在意识到这是可行的(仍然是 WIP):

match /leagues/{league} { 
    allow read, create, update: if request.auth.uid != null; 

    //only ever deleting a single league at a time 
    allow delete: if exists(/databases/$(database)/documents/leagues/$(league)/users/$(request.auth.uid));

    match /{docs = **} { 
        allow read, write: if exists(/databases/$(database)/documents/leagues/$(league)/users/$(request.auth.uid))} 
}

而且我有点理解发生了什么(在一个请求中读取/写入可能超过一个联赛时,我不能使用 {league} 通配符?),但我仍然不确定为什么?

【问题讨论】:

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


    【解决方案1】:

    谁能告诉我为什么这条规则有效:

    match /leagues/{league} {
        allow read, write: if resource.data.ABCDEF123 != null;
    

    但不是这个:

    match /leagues/{league} {
        allow read, write: if resource.data.request.auth.uid != null;
    

    我猜resource.data 中没有名为request 的字段。点语法应该如何知道您要先评估最后一部分(request.auth.uid)并将结果用作下一个键?我不确定,但你可以试试resource.data[request.auth.uid]

    另外,为什么这条规则有效:

    // "ZYXWV987" is an example of a league the user is in 
    match /leagues/{league} {
        allow read, write: if exists(/databases/$(database)/documents/leagues/$('ZYXWV987')/users/$(request.auth.uid));
    

    但不是这个:

    match /leagues/{league} {
        allow read, write: if exists(/databases/$(database)/documents/leagues/$(league)/users/$(request.auth.uid));
    

    来自docs on security rules

    来自 Cloud Firestore 移动/网络客户端的每个数据库请求 阅读或 写入任何数据。

    评估第一条规则,根据结果,允许用户阅读所有或无联赛文件。 第二条规则必须针对每个文档进行评估,具体取决于内容。在全部阅读之前这是不可能的。

    您必须以 Firestore 仅根据查询的定义独立于可能的结果来评估它们的方式定义您的安全规则。

    【讨论】:

    • resource.data[request.auth.uid] 有效!其余的也很有意义。谢谢!
    • 后续问题:如果该字段的值为 FieldValue,我如何在删除字段时检查 FS 规则(即“documentReference.update(fieldID, FieldValue.delete();”)。 delete() ? "request.writeFields 中的request.auth.uid" 给了我"true",但是"request.resource.data[request.auth.uid] != null" 和"request.resource.data[request. auth.uid] = null" 都给我“假”/“错误”(我不知道如何检查)
    • 我不太明白您要做什么,只是为了确保这不是错字 - 您尝试过 ==空?
    • 哈,这是一个错字,但不是我的实际规则!这是不起作用的完整规则(目前,用于故障排除):allow update: if request.auth.uid in request.writeFields && (request.resource.data[request.auth.uid] == null || request.resource.data[request.auth.uid] != null);
    • 在我的应用程序中,用户可以在docref.update(userID, level) 组中更改其访问级别或将自己完全删除docref.update(userID, FieldValue.delete()),并且用户是文档中的所有字段(以访问级别为值)。 .. 更新级别适用于上述规则,但删除不适用...此外,删除用户只适用于allow update: if request.auth.uid in request.writeFields
    猜你喜欢
    • 1970-01-01
    • 2018-08-29
    • 2020-09-18
    • 2019-12-02
    • 2012-02-04
    • 1970-01-01
    • 2018-10-19
    • 2019-07-05
    • 2022-12-11
    相关资源
    最近更新 更多