Firebase 安全规则阻止写入 Firebase

Posted

技术标签:

【中文标题】Firebase 安全规则阻止写入 Firebase【英文标题】:Firebase Security Rules Block Writing to Firebase 【发布时间】:2016-03-23 17:34:47 【问题描述】:

注意:这个问题被标记了 polymer 因为Polymer库是用来生成javascript的。

这个问题是关于处理 Firebase 安全性的两个不同但相关的问题。在尝试使 Firebase 安全规则发挥作用时,问题 1 和问题 2 似乎暗示了相反的现实和相反的结果。 (FWIW:Here is my prior unsuccessful attempt to write this question。)

Here is the live code in a JSBin.

http://jsbin.com/hinehoyigo/edit?html,output

问题 1

说明

    输入您的 Firebase ID。示例:“hot-sauce-123” 在新标签页或窗口中,转到您的 Firebase 并将其打开 允许匿名身份验证: 你的火力基地 > 登录和验证 > 匿名标签 > 勾选“启用匿名用户验证” 不应用安全规则:安全与规则 > “规则”: “.read”:是的, “.write”:真 返回jsbin 选择“匿名”作为身份验证提供者:下拉菜单 > 匿名 单击标有“登录”的按钮 验证右侧每个字段的登录状态 打开您的控制台:Chrome > 查看 > 开发人员 > 开发人员工具 单击标有“将用户打印到控制台”的按钮 通过验证打印到控制台的用户对象来双重检查登录状态 单击标有“将 Firebase 打印到控制台”的按钮 通过检查打印到控制台的 Firebase URL 来验证正确的 firebase 点击标有“写入 Firebase - 普通网址”的按钮 检查您的 Firebase 数据;注意没有写入发生 单击标有“写入 Firebase — .json 网址”的按钮 检查您的 Firebase 数据;通知写入成功 区分两次写入尝试,因为前一次尝试写入 "quux":"baz"; 后者尝试写 "jquux":"jbaz" 添加安全规则:安全和规则 > “规则”: “用户”: "$uid": ".read": "auth != null && auth.uid === $uid", ".write": "auth != null && auth.uid === $uid" 再次单击标有“写入 Firebase — .json 网址”的按钮 检查您的 Firebase 数据;注意写现在失败 结论/问题陈述:。

问题 2

模拟器阻止 .json URL 被使用(如上所述)

说明

    打开您的 Firebase 验证安全规则是否到位(参见上述问题 #1 中的步骤 #19)... 打开您的模拟器:垂直导航菜单 > 模拟器 选中标记为“自定义身份验证”的单选按钮 自定义身份验证输入字段应类似于 “提供者:'匿名',uid:'ag69g401-f097-4171-bca4-927fd1a6e1f3'” 单击标有“身份验证”的按钮 验证小绿色复选标记位于标有“自定义身份验证”的单选按钮旁边 转到第 2 节 点击标签为“写”的标签 在标有 URL 的输入字段中,输入“users/ag69g401-f097-4171-bca4-927fd1a6e1f3/foo/bar” 验证您刚刚输入的 URL 路径中的用户 ID,是否与上述自定义身份验证字段中的 uid 值匹配 单击标有“模拟写入”的按钮 通知回复说: 尝试用auth="provider":"anonymous","uid":"ag69g401-f097-4171-bca4-927fd1a6e1f3""key":"value" to /users/ag69g401-f097-4171-bca4-927fd1a6e1f3/foo/bar
    /
    /用户
    /users/ag69g401-f097-4171-bca4-927fd1a6e1f3:.write: "auth != null && auth.uid === $uid"
        => 是的
    允许写入。 注意:此结果与上述步骤 #14 和 #15 的结果相反,其中纯 URL(未附加 .json)无法写入 将“.json”附加到 URL,以便输入字段读取类似 “用户/ag69g401-f097-4171-bca4-927fd1a6e1f3/foo/bar.json” 单击标有“模拟写入”的按钮 通知回复说: 路径无效。模拟中止。 注意:此结果与上述步骤 #16 和 #17 的结果相反,其中 .json 附加 URL 是唯一有效的; 请注意,这些模拟器测试显示的结果与上述问题 #1 中的实时代码测试结果相反

【问题讨论】:

【参考方案1】:

问题 1

您正在使用 Polymer firebase-auth 元素向 Firebase 进行身份验证。

<firebase-auth id="firebaseLogin"
               user="user"
...

在后台调用Firebase.authAnonymously() 方法,该方法验证Firebase JavaScript SDK 中的当前会话。

您正在使用以下方式向 Firebase 写信:

computeFbTargetJson: function(f) 
    return f + '.json';

this.set('$.ajax.url'  , this.fbTargetJson);
this.set('$.ajax.body' , JSON.stringify(
    jquux: 'jbaz'
   ));
this.$.ajax.generateRequest();

这是向 Firebase 发出 AJAX 请求,这意味着您正在使用 Firebase's REST API。但由于这是一个常规的 HTTP 调用,它不会“继承”来自 Firebase JavaScript 客户端的身份验证。

要验证您的 REST 请求,您需要pass in an auth parameter as documented in the Firebase documentation。您可以使用 ref.getAuth().token 从 Firebase 参考中获取令牌。

问题 2

Firebase 数据库中的每个元素都可以通过唯一的 URL 访问。您可以使用其中一个 Firebase SDK 访问它,也可以直接访问 Firebase 公开的 REST API。

根据我从 jsbin 收集到的信息,您正在使用以下方式写信给 Firebase:

computeFbTargetJson: function(f) 
    return f + '.json';

this.set('$.ajax.url'  , this.fbTargetJson);
this.set('$.ajax.body' , JSON.stringify(
    jquux: 'jbaz'
   ));
this.$.ajax.generateRequest();

这是向 Firebase 发出 AJAX 请求,这意味着您正在使用 Firebase's REST API。该 API 文档的第一段解释了 Firebase 数据库 URL 如何映射到 REST API:

我们可以使用任何 Firebase 应用 URL 作为 REST 端点。我们需要做的就是将 .json 附加到 URL 的末尾,然后从我们最喜欢的 HTTPS 客户端发送请求。

因此,为了使用 REST API 访问 Firebase 中的任何数据,您需要将 .json 附加到该数据的 URL。

当您使用 Firebase 模拟器时,操作类似于使用 Firebase 的 JavaScript SDK。在这种情况下,您不应将.json 后缀放在 URL 的末尾。

假设有一个位于 https://mine.firebaseio.com/ 的 Firebase 数据库,假设您有一个位于 /users/de01fc8104 的用户个人资料。

您可以在模拟器中或使用 Firebase SDK 作为https://mine.firebaseio.com/users/de01fc8104 访问该记录 要使用 REST API 访问记录,URL 是 https://mine.firebaseio.com/users/de01fc8104.json

总结

您的这两个问题都是由于您使用两种不同的方式访问 Firebase 造成的:JavaScript SDK 和 REST API。虽然这两种方法可以一起使用,但您必须确保提供所需的信息。一般来说,如果您坚持使用从单个客户端访问 Firebase 的一种方式,您将获得更轻松的体验。

【讨论】:

感谢您的出色回答。 (+1) 顺便说一下,I noticed this page is about User Authentication 位于左侧的导航菜单中,但页面标题的标题为 User Authorization。因此,Firebase 中的某个人可能想要决定什么是什么,并使两者匹配,就像其他页眉匹配他们的菜单标签一样。这种差异真的触发了我的强迫症。【参考方案2】:

@FrankvanPuffelen's answer 在 Polymer-speak 中翻译成:

Use the &lt;firebase-collection&gt; element's .add() method 在执行安全规则时将数据从客户端写入 Firebase。从代码的角度来看,它更有效,因为firebase-collection 会自动为您处理所有必要的身份验证令牌。

【讨论】:

以上是关于Firebase 安全规则阻止写入 Firebase的主要内容,如果未能解决你的问题,请参考以下文章

Firebase 安全规则:限制仅写入此 uid,几个字段除外

Firebase 数据库安全规则允许经过身份验证的用户读取和写入自己的内容

用户扫描二维码以读取和写入特定数据库节点后如何在 Firebase 中设置安全规则

Firebase 实时电话数据库安全规则

由于异常活动,我们已阻止来自此设备的所有请求 - Flutter 应用上的 Firebase

安全规则中的 Firebase 速率限制?