【问题标题】:Security rules and query for a document sharing app文档共享应用程序的安全规则和查询
【发布时间】:2019-09-18 08:36:02
【问题描述】:

我制作了一个具有协作功能的笔记式应用程序,并希望设置安全的安全规则。 问题是:我的安全规则不适用于我的数据库查询。 当我测试经过身份验证的用户对笔记的访问权限时,Firebase 安全规则模拟器显示正确的结果。 但在应用程序中,我收到消息“/notes 的侦听器失败:permission_denied”。

我在这里找到了一些很好的安全规则示例 Firebase: Security rules for a collaborative app 和这里 https://gist.github.com/katowulf/4741111 但这些与我所拥有的并没有什么不同。 我怀疑问题可能出在查询中或缺少索引规则(“.indexOn”)。

我的查询是:

- (void)setupQuery {    

    NSString *email = [FirebaseAuthorization shared].currentUserEmail;

    self.reference = [[[FIRDatabase database] reference] child:@"notes"];

    NSString *query = [NSString stringWithFormat:@"document/users/%@", email.MD5String];

    self.query = [[self.reference queryOrderedByChild:query] queryEqualToValue:@(YES)];

}

我的安全规则是:

{
  "rules": {
    "notes" : {

      "$note_id" : {
        ".read": "data.child('document/users/'+root.child('users/'+auth.uid+'/email_md5').val()).val() === true",
        ".write": "(data.child('document/users/'+root.child('users/'+auth.uid+'/email_md5').val()).val() === true) || (root.child('users/'+auth.uid+'/email').val() === root.child('users/'+newData.child('document/author').val()+'/email').val())",

        ".indexOn": "document/users"
        }      
    },
    "users" : {
      "$user_id" : {
        ".read": "auth.uid === $user_id",
        ".write": " ( auth.uid == newData.val() ) || ( auth.uid == $user_id )"
      }    
    }
    }
  }

而我的数据库结构是:

{
"notes" : {
  "NOTE_ID_1" : {
    "document" : {
      "author" : "user_id_1",
      "users" : {
        "email_1_md5@email-com" : true,
        "email_2_md5@email-com" : true
        }
      }
    }
  "NOTE_ID_2" : {
    "document" : {
      "author" : "user_id_2",
      "users" : {
        "email_3_md5@email-com" : true,
        "email_4_md5@email-com" : true,
        }
      }
    }
}
"users" : {
  "iser_id_1" : {
    "email" : "email_1@email.com",
    "email_md5" : "email_2_md5@email-com"
    }
  }
}

我希望查询能够使用严格的安全规则(每个用户只能访问他的笔记),但现在它只能使用宽松的安全规则(每个用户都可以访问所有笔记)。

【问题讨论】:

    标签: objective-c firebase firebase-realtime-database firebase-authentication firebase-security


    【解决方案1】:

    Firebase 安全规则不会代表您过滤数据。他们只是强制所有数据访问都是经过授权的。

    这是您查询的代码

    self.reference = [[[FIRDatabase database] reference] child:@"notes"];
    
    NSString *query = [NSString stringWithFormat:@"document/users/%@", email.MD5String];
    
    self.query = [[self.reference queryOrderedByChild:query] queryEqualToValue:@(YES)];
    

    为了运行此代码,用户必须在notes 拥有某种形式的读取权限。由于没有人对该节点具有读取权限,因此规则引擎拒绝读取。

    这在文档中称为rules are not filters,在许多其他questions about the topic 中。


    请注意,您现在可以通过query-based rules 使用安全规则来允许对某些查询进行读取。使用此功能时,您在代码中构建相关查询,然后使用安全规则仅允许使用该特定查询访问数据。

    在您的情况下,这将是 /notes 上的 .read 规则,它与您正在构建的查询相匹配。对于您的用例,它会是这样的

    {
      "rules": {
        "notes" : {
          ".read": "
            query.orderByChild == 'document/users/'+auth.uid &&
            query.equalTo == true
          "
        }
      }
    }
    

    请注意,我不确定这个条件是否真的符合您的查询。

    即使是这样,缺少索引也会使安全点变得毫无意义(因为没有索引,所有过滤都在客户端完成)。有关更多信息,请在此处查看我的答案:Firebase query if child of child contains a value。这种倒排索引还允许您在扇出(写入)逻辑中而不是在读取操作中实现安全性,从而确保更好的读取可扩展性。

    【讨论】:

    • 谢谢你,弗兰克。我正在尝试您提出的规则,但出现错误消息: Invalid == expression: right operand must be an ordering or string literal when comparison with an ordering.
    • 是的,我害怕这样的事情。您可能想尝试('document/users/'+auth.uid),但目前我猜。鉴于我对性能的说明,我建议查看倒排索引。
    • 它给出了相同的结果。倒排索引应该更简单,但恐怕它不太健壮。
    • 倒排索引可能不太安全。如果任何用户可以写入该用户的可访问笔记列表,则第三方可以修改该用户对共享给他的笔记的访问权限。
    • Frank,您认为 Firestore 更容易实现吗?这是一项投资,但在应用发布之前仍有一定的灵活性
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-19
    • 1970-01-01
    • 1970-01-01
    • 2019-02-01
    • 2016-11-23
    • 1970-01-01
    相关资源
    最近更新 更多