【问题标题】:Allowing specific user write access允许特定用户写访问
【发布时间】:2015-01-23 18:04:33
【问题描述】:

我的 Firebase 读/写规则有点受阻。我希望我有办法在检查身份验证时设置断点(没有办法,是吗?)。

我的问题很简单,我觉得我应该能够更好地理解它。我觉得大部分源于对规则的不完全理解。此信息用于在线查看产品的简单方法,并且所有者需要能够添加产品。所以我希望世界能够阅读,而登录的人能够写作。

我的数据如下:

app
 Users
    email: xxx@xxx.com
 product
   0
     name: pizza

还有我的规则:

 {
    "rules": {
      "product":{
        ".read": true,
        ".write":"root.child('Users').child(auth.uid).child('email').val() === 'testuser@test.com'"
      }
    }
}

我不太明白这意味着什么。我真的只想说,如果用户已登录,则允许写入功能。我希望我可以像".write": "auth" 这样的东西,这意味着如果身份验证存在(用户已登录)然后让他写。但我显然不完全理解规则是如何运作的。我正在使用简单的电子邮件/密码身份验证。

如何测试这些规则以及如何向它们传递参数?

【问题讨论】:

    标签: firebase firebase-security


    【解决方案1】:

    我将尝试解释您的.write 安全规则,即:

    "root.child('Users').child(auth.uid).child('email').val() === 'testuser@test.com'"
    

    这确实不是最容易开始的规则,Firebase 文档无疑会很快深入。

    在我使用 twitter 登录我的应用程序后,我的代码将获得一个告诉它的 authData 变量:

     authData
         uid: "twitter:4511241"
         provider: "twitter"
         id: "4511241"
    

    可能还有更多属性,但这应该是它的要点。 authData 通常包含一个子对象,该对象具有特定于提供者的属性,因此在本例中为twitter,您通常可以在那里找到一些非常有趣的东西。例如在 Twitter 的情况下,用户的 Twitter 名称。

     authData
         uid: "twitter:4511241"
         provider: "twitter"
         id: "4511241"
         twitter:
             userName: "puf"
             email: "puf@twitter.com" // note: this is just an example email address,
                                      // it doesn't exist (as far as I know)
    

    此对象可供我的代码使用,默认情况下它不存储在 Firebase 中的任何位置。

    在您的安全规则中,您可以检查相同的结构。但这里只有最小的信息子集,足以识别用户。 Firebase documentation for the auth object 命名这些属性:

    提供者 |使用的身份验证方法(“密码”、“匿名”、“facebook”、“github”、“google”或“twitter”)。

    uid |唯一的用户 ID,保证在所有提供商中都是唯一的。

    使用这些属性,我们已经可以允许特定用户对我们的数据进行写访问。就像我在对您的回答的评论中所说的那样:

    ".write": "auth.uid = 'twitter:4511241'"
    

    这将允许我在使用@puf twitter 帐户登录时写入数据。但不幸的是,它不允许我检查对用户更友好的属性,例如电子邮件地址。

    一种常见的做法是在您的 Firebase 中创建一个顶级 Users 节点,并为该节点下的所有用户添加由其 uid 标识的所有信息。所以在我上面的例子中:

     Users
         twitter:4511241
             userName: "puf"
             displayName: "Frank van Puffelen"
             email: "puf@twitter.com"
         github:913631
             userName: "puf"
             displayName: "Frank van Puffelen"
             email: "puf@github.com"
    

    我把 provider 和 id 留在这里,因为它们没有为示例提供太多价值

    当您知道用户的uid时,您可以在此节点中查找他的附加信息。这正是您之前的安全规则所做的:

    "root.child('Users').child(auth.uid).child('email').val() === 'testuser@test.com'"
    

    因此,这将从您的 Firebase 的根目录查找名为 Users 的节点,然后查找登录用户的 uid 以及他/她的电子邮件地址。

    检查特定电子邮件地址的好处在于它与用户的提供商无关。因此,无论用户是使用 twitter、github、facebook 还是其他支持的提供商登录,只要他们为每个帐户使用相同的电子邮件地址,他们就可以写入数据。

    【讨论】:

    • 这个解释太棒了。感谢您的大力投入。那么,如果将我在 firebase 中的用户“对象”更改为 Users -> id -> email: testuser@test.com 我原来的条件会起作用吗?
    • 电子邮件匹配似乎是个不错的主意,但这里有安全风险吗?即,如何填充数据库中的 /Users 节点?如果它是由客户端通过正常的 REST 动词而不是由 firebase 服务填充的,那么有什么能阻止我拦截我的个人资料信息到 /Users 的插入并输入我喜欢的任何电子邮件地址,例如joefoo@foefoo.com?如果 joefoo 有您的服务帐户,那么现在我似乎可以在 firebase 数据库中访问他的东西了。 编辑 刚刚看到@PavelGeorgiev 的评论说的基本相同。
    【解决方案2】:

    执行以下操作似乎可以解决问题。如果 auth 变量存在,则允许写入能力。由于我没有完全理解这些规则,我不得不怀疑这是否针对当前用户运行,或者它是否正在检查是否有任何用户登录。

    {
        "rules": {
          "product":{
            ".read": true,
            ".write":"auth !== null"
          }
        }
    }
    

    【讨论】:

    • 您好 Aarmora,这确实将允许每个人读取访问权限以及任何登录的用户写入产品节点。一个允许特定用户写入的简单示例是".write": "auth.uid = "twitter:4511241"。该值是我使用 twitter 进行身份验证时在我的一个应用程序中拥有的 uid。由于这些 uid 不是最容易获得的,因此查找例如.write 规则中用户的电子邮件地址,这正是您问题中的示例所做的。
    • 我会写一个答案,看看我是否能解释这个规则。
    猜你喜欢
    • 1970-01-01
    • 2012-04-16
    • 1970-01-01
    • 2011-12-03
    • 2021-02-03
    • 2020-09-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多