【问题标题】:Firestore which rule for read only from Android app and write using API KEY?Firestore 哪个规则用于从 Android 应用程序只读并使用 API KEY 写入?
【发布时间】:2019-02-25 10:57:24
【问题描述】:

我对 Firestore 的安全规则有疑问。

我的场景是这样的:用户只会读取数据的 Android 应用程序。他们不会保存,他们不会修改任何东西。他们不会注册。这只是数据读取。

就我而言,我需要在该集合中写作。我打算通过 cURL 使用 API KEY 来实现。

我使用的规则如下:

  match /mycol/{document=**} {
  allow read: if request.auth.uid != null; allow  write: if true;
}

我想阻止我的收藏被访问,例如从任何地方通过 URL:

https://firestore.googleapis.com/v1/projects/myproject/databases/(default)/documents/mydoc/mycol/

例如避免机器人发出不加选择的请求,这会增加我的账单......

我正在为这种情况实施良好的规则(仅从未经身份验证的 Android 应用读取并使用 API KEY 通过 cURL 写入)?

【问题讨论】:

  • 您不能使用安全规则来限制 Firestore 的流量来源。它可能来自 Android 应用程序、iOS、Web 或 REST API。您可以做的是根据正在访问数据的经过身份验证的用户限制访问,这将在下面的答案中讨论。

标签: android firebase google-cloud-firestore


【解决方案1】:

您并没有真正关闭您的收藏,相反,您允许任何人对其进行写入。

为了只允许您自己写入集合,有几个选项。您可以使用Admin SDK 并编写一个只能在您的机器上运行的小程序。

Admin SDK 忽略安全性,因此您可以删除写入部分,它只对您有效。

match /mycol/{document=**} {
  allow read: if request.auth.uid != null;
}

这可能是最简单的选择,而且很安全,只要您保证您的凭据安全并且只在受信任的机器/网络中执行此操作。

另一种选择是为自己创建一个用户并与该用户进行身份验证。例如,它可以是移动应用程序、Web 应用程序或 Node 应用程序。通过这样做,您可以为您的用户创建自定义声明,并且只允许拥有该声明的用户编写,如下所示:

match /mycol/{document=**} {
  allow read: if request.auth.uid != null; allow write: if request.auth.token.admin;
}

然后您可以像这样(从节点)向用户设置声明:

await admin.auth().setCustomUserClaims("user_user_id", { admin: true });

另一个选择是创建一个云函数来写入该集合。 Cloud Functions 使用 Admin SDK,因此安全规则也不适用,除非您希望使用 Javascript 客户端 SDK 来代替。然后在 Cloud Function 中您可以验证您的 API 密钥,并且您将始终调用 Cloud Function 的 URL 而不是直接调用数据库。

我会选择第一个选项,以便您熟悉 Admin SDK,然后如果需要,您可以升级到更结构化的解决方案。

【讨论】:

  • 谢谢里卡多。安全规则让我感到困惑。只留下这个:match /mycol/{document=**} { allow read: if request.auth.uid != null; },我在我的 logcat 中看到这条消息:com.google.firebase.firestore.FirebaseFirestoreException: PERMISSION_DENIED: Missing or insufficient permissions 我不明白应用什么规则来允许仅从 Android 读取。
  • 您的规则仅限于经过身份验证的用户。解决这个问题的一种方法是在 Android 上创建一个匿名登录:firebase.google.com/docs/auth/android/anonymous-auth,或者您也可以通过将规则设置为仅allow read; 并仅保护写入来让任何人阅读。
  • 如果我离开allow read;,如果机器人向该路由中我的集合/文档的 URL 发送不加选择的请求,会发生什么情况?我正是想避免我的账单出现意外
  • 是的,那会是个问题。也许在这种情况下,使用固定密码创建单个用户并使用它进行身份验证会更有趣。如果您的密码泄漏,这只会是一个问题,但有一些方法可以缓解这种情况,例如创建当前日期的哈希并将其用作密码。
  • 在 Google 控制台上看到我有 Android 客户端的凭据,我不能用它在 Firestore 上永久授权我的应用程序吗?事实上,我认为我的应用程序应该很容易被 Firestore 识别,但我不知道应该应用什么规则才能做到这一点。那么,在我将 Firestore 添加到我的 Android 应用程序时创建的控制台中的那些凭据有什么用?
【解决方案2】:

由于您尝试仅针对某些条件进行只读和写操作。请尝试使用此规则。这里在条件中指定 api 键(如果有):

   service cloud.firestore {
      match /databases/{database}/documents {
        match /<some_path>/ {
          allow read: if <some_condition>;
         allow write: if <some_condition>;
}
      }
    } 

要仅针对您的应用程序,您应该为此获取应用程序令牌,只需执行以下操作:

FirebaseInstanceId.getInstance().getInstanceId().addOnSuccessListener(this, instanceIdResult -> {
    String newToken = instanceIdResult.getToken();
    Log.e("newToken", newToken);
});

运行此代码后,转到您的日志,然后复制令牌,然后简单地在您的条件中指定该令牌,尝试使用您的应用程序令牌创建一个身份验证 ID,然后将该身份验证 ID 与您的数据库规则中的应用程序令牌进行比较

【讨论】:

  • 谢谢。我的问题正是关于条件。 1. 什么条件可以只从应用程序中读取而不需要用户注册? 2. 什么条件允许我只使用 API KEY 进行写入和访问?
  • 检查我更新的答案,如果你仍然没有得到它,请回击我,我会给你做代码的步骤
  • 很抱歉,我不太了解您告诉我的有关令牌的内容。这是每次对 Firebase 的额外请求吗?这不会增加我的账单吗?没有更简单的方法吗?
  • 令牌是由 firebase 生成以识别特定应用程序的唯一标识,因此当您获取应用程序生成的令牌并在您的规则中指定它时,默认情况下只允许您的应用程序访问数据库
  • @A.Cedano 如果您希望您的应用程序仅访问数据库,这是解决您的问题的最简单的解决方案,而且我认为除此之外还有其他解决方案能够实现你想要的
猜你喜欢
  • 1970-01-01
  • 2020-12-18
  • 2021-03-30
  • 2019-08-15
  • 2019-09-28
  • 2021-12-11
  • 2019-12-31
  • 2021-07-11
  • 1970-01-01
相关资源
最近更新 更多