1

花了几天时间尝试不同的、各种推荐的方法来做到这一点,我已经找到了我认为最简单和最有希望的方法。还要感谢来自这个 SO 问题的好心人:Get the index ID of an item in Firebase AngularFire

当前设置

用户可以使用电子邮件和社交网络登录,因此当他们创建记录时,会将其保存userId为一种外键。

在此处输入图像描述

目前很好。但我想创建一个规则,所以twitter2934392无法读取facebook63203497的记录。

关闭安全面板

在此处输入图像描述

匹配后端的 ID

不幸的是,文档与方法不一致,firebase 用户 ID 每个提供商(facebook、twitter、密码)都是唯一的,这建议将社交网络附加到 ID。文档希望您为每个登录方法的 id 创建不同的规则。为什么使用 >1 登录方法的任何人都想这样做,这超出了我的理解。

在此处输入图像描述

(来自:https ://www.firebase.com/docs/security/rule-expressions/auth.html )

因此,我将尝试将连接auth.provider的 with 与相应项目auth.id的记录相匹配。userIdregistry

根据 API,这应该像

在此处输入图像描述

在我的情况下,当然使用$registry而不是$user

{
  "rules": {
    ".read": true,
    ".write": true,
    "registry": {
      "$registry": {
        ".read": "$registry == auth.id"
      }
    }
  }
}

但这不起作用,因为(参见上面的第一张图片),AngularFire 将每条记录设置在一个索引值下。在上图中,它是0. 这就是事情变得复杂的地方。

此外,我无法在模拟器中测试任何东西,因为我无法编辑{some: 'json'}甚至进行身份验证。输入框拒绝任何输入。

在此处输入图像描述

我最好的猜测如下。

{
  "rules": {
    ".write": true,
    "registry": {
      "$registry": {
        ".read": "data.child('userId').val() == (auth.provider + auth.id)"
      }
    }
  }
}

这既会引发身份验证错误,又会同时向所有用户授予完全读取权限。我正在失去理智。我应该在这里做什么?

4

2 回答 2

0

伪造模拟器中的自定义身份验证不是最好的,但是如果您在选择输入后按 Tab 键,它可以让您粘贴或编辑该字段。此时您可以添加{"provider":"facebook","id":"63203497"}{"provider":"twitter","id":"2934392"}希望从中获得一些有用的调试。

假设你的火力基地是这样的:

{"registry":{
"0":{
    "id":"abbacadaba123",
    "index":"0",
    "name":"New Device",
    "userId":"facebook63203497"},
"1":{
    "id":"adaba123",
    "index":"1",
    "name":"Other Device",
    "userId":"twitter2934392"}

}
}

这可能适用于安全规则:

{
    "rules": {
        "registry":{
            "$registryId":{
                ".read":"data.child('userId').val() === (auth.provider + auth.id)",
                ".write":"(data.child('userId').val() === (auth.provider + auth.id))||(auth != null && !data.exists())",
                ".validate": "newData.hasChildren(['id', 'index', 'name', 'userId'])",
                "id": {
                    ".validate":"newData.isString()"
                },
                "index": {
                    ".validate":"newData.isNumber()"
                },
                "name": {
                    ".validate":"newData.isString() && newData.val().length >= 1"
                },
                "userId": {
                    ".validate":"newData.val() === (auth.provider + auth.id)"
                }
            }
        }

    }
}

您的读取规则按预期测试。facebook 用户在注册表 0 上读取测试为真,在 1 上测试为假。twitter 用户在 0 上为假,在 1 上为真。我对 .write 和 .validate 规则进行了几次快速测试,它们似乎有效。

希望这至少有助于排除 Firebase 安全规则部分,因此您可以专注于 AngularFire 绑定部分。

于 2013-10-31T02:14:18.593 回答
0

我认为您不想将特定于用户的数据存储在非特定于用户的索引下。将用户数据存储在有意义的键后面,而不是push()ing 到您的 firebase 引用。

例如

auth.createUser(email, password, function(error, user) {
  if (!error) {
    usersRef.child(user.id).set(stuff);
  }
});

现在,您实际上可以根据经过身份验证的用户来获取用户数据。

于 2013-10-21T03:49:47.027 回答