向公众公开 Firebase apiKey 是否安全?

IT技术 javascript firebase
2020-12-30 15:55:41

火力地堡web应用指南规定我应该把给定的apiKey在我的HTML初始化火力地堡:

// TODO: Replace with your project's customized code snippet
<script src="https://www.gstatic.com/firebasejs/3.0.2/firebase.js"></script>
<script>
  // Initialize Firebase
  var config = {
    apiKey: '<your-api-key>',
    authDomain: '<your-auth-domain>',
    databaseURL: '<your-database-url>',
    storageBucket: '<your-storage-bucket>'
  };
  firebase.initializeApp(config);
</script>

通过这样做,apiKey每个访问者都可以看到

该密钥目的是什么,它真的意味着要公开吗?

6个回答

apiKey这个配置片段只是标识了谷歌服务器上的火力地堡项目。有人知道它不是安全风险。事实上,他们有必要了解这一点,以便他们与您的 Firebase 项目进行交互。每个使用 Firebase 作为后端的 iOS 和 Android 应用程序中也包含相同的配置数据。

从这个意义上说,它与在同一片段中标识与您的项目关联的后端数据库的数据库 URL 非常相似:https://<app-id>.firebaseio.com. 请参阅有关为什么这不是安全风险的问题:如何限制 Firebase 数据修改?,包括使用 Firebase 的服务器端安全规则来确保只有经过授权的用户才能访问后端服务。

如果您想了解如何确保对 Firebase 后端服务的所有数据访问均获得授权,请阅读有关Firebase 安全规则的文档这些规则控制对文件存储和数据库的访问,并在 Firebase 服务器上强制执行。因此,无论是您的代码,还是使用您配置数据的其他人的代码,它都只能执行安全规则允许的操作。

有关 Firebase 将这些值用于什么目的以及您可以为其中哪些设置配额的另一说明,请参阅有关使用和管理 API 密钥的 Firebase 文档


如果您想降低将此配置数据提交给版本控制的风险,请考虑使用Firebase HostingSDK 自动配置虽然密钥仍会以相同的格式出现在浏览器中,但它们将不再被硬编码到您的代码中。


更新(2021 年 5 月):借助名为Firebase App Check的新功能,现在实际上可以将 Firebase 项目中后端服务的访问权限限制为仅来自在该特定项目中注册的 iOS、Android 和 Web 应用程序的访问.

通常你会想这与上述基于安全的用户认证相结合,让你有针对滥用用户的另一屏蔽部使用你的应用程序。

通过将 App Check 与安全规则相结合,您既可以广泛地防止滥用,又可以很好地控制每个用户可以访问的数据,同时仍然允许从客户端应用程序代码直接访问数据库。

如果 bot 在我的应用程序中创建无限用户怎么办。我怎么需要验证码。
2021-02-07 15:55:41
@m.rufca ,您的数据应该可供经过身份验证的用户使用。这就是诀窍。默认情况下,在您的 Firebase 设置中,只有 localhost 和您的项目域有权从它们执行身份验证。因此,没有其他人可以创建通常与您的 Firebase 一起使用的应用程序。
2021-02-07 15:55:41
在这里找到了我最后一个问题的答案support.google.com/firebase/answer/6400741感谢您的帮助。此链接将来可能会对某人有所帮助。
2021-02-16 15:55:41
所以这意味着其他人将能够访问我的 firebase 数据库中的所有数据?
2021-03-05 15:55:41
@EmmanuelCampos 答案是是和否。是的,如果您允许或希望其他人访问数据库中的所有数据。不,如果你不希望他们这样做。Firebase 数据库有规则,你控制的规则
2021-03-06 15:55:41

建立在prufrofro和弗兰克面包车Puffelen的答案在这里,我放在一起这个设置并不妨碍刮,但可以让它稍硬使用您的API密钥。

警告:要获取数据,即使使用这种方法,您也可以简单地在 Chrome 中打开 JS 控制台并输入:

firebase.database().ref("/get/all/the/data").once("value", function (data) {
    console.log(data.val());
});

只有数据库安全规则才能保护您的数据。

尽管如此,我将我的生产 API 密钥的使用限制为我的域名,如下所示:

  1. https://console.developers.google.com/apis
  2. 选择您的 Firebase 项目
  3. 证书
  4. 在 API 密钥下,选择您的浏览器密钥。它应该是这样的:“浏览器密钥(由 Google 服务自动创建)
  5. 在“接受来自这些HTTP参照请求(网站) ”中,增加您的应用程序的URL(为例:projectname.firebaseapp.com/*

现在该应用程序将仅适用于该特定域名。所以我创建了另一个 API 密钥,它将是本地主机开发的私有密钥。

  1. 单击创建凭据 > API 密钥

默认情况下,正如 Emmanuel Campos 所提到的,Firebase 仅白名单localhost和您的 Firebase 托管域


为了确保我不会错误地发布错误的 API 密钥,我使用以下方法之一在生产中自动使用更受限制的一个。

Create-React-App 的设置

/env.development

REACT_APP_API_KEY=###dev-key###

/env.production

REACT_APP_API_KEY=###public-key###

/src/index.js

const firebaseConfig = {
  apiKey: process.env.REACT_APP_API_KEY,
  // ... 
};
到目前为止我没有遇到任何问题,但可能也没有攻击
2021-02-07 15:55:41
这对你来说工作正常吗?正在考虑为 Android 应用程序做同样的事情。我想知道为什么 Firebase 在安全部分没有涵盖这一点。
2021-02-18 15:55:41
在“接受来自这些 HTTP 引用者(网站)的请求”中,添加您的应用程序的 URL(例如:projectname.firebaseapp.com/*)这不起作用。
2021-02-18 15:55:41
@FrankvanPuffelen 据我了解,这并没有什么大的区别,但可能会使滥用配额变得更加烦人,因为在行为良好的浏览器中,与 HTML/JS 一起提供的 API 密钥仅适用于预期的域,而不是本地主机或其他任何东西。但我同意,与 Firebase 已经提供的相比,增加的保护是微不足道的。我会改写一些不那么戏剧化的答案。
2021-02-24 15:55:41
他们的指南中没有提到这一点,因为它不会保护您免受刮擦。所有这些都确保其他人无法制作使用您的 Firebase 读取(或写入)数据的网络应用程序,如果它在正常运行良好的浏览器中运行。
2021-03-01 15:55:41

我不相信向客户端公开安全/配置密钥。我不会称之为安全,不是因为有人可以从第一天起窃取所有私人信息,因为有人可以提出过多的请求,耗尽你的配额,让你欠谷歌很多钱。

您需要考虑许多概念,包括限制人们不要访问他们不应该去的地方、DOS 攻击等。

我更希望客户端首先访问您的 Web 服务器,在那里您可以在客户端和服务器之间或服务器和 Firebase 之间放置第一手防火墙、验证码、cloudflare、自定义安全性,然后就可以了。至少您可以先停止可疑活动,然后再到达火力基地。您将拥有更大的灵活性。

我只看到一种使用基于客户端的配置进行内部使用的良好使用场景。例如,您有内部域,并且您很确定外部人员无法访问那里,因此您可以设置浏览器-> firebase 类型等环境。

在浏览器中公开密钥是一个严重的坏主意。那些写所有这些指南/文章的人,他们在想什么?安全性的 http 引荐来源网址?很容易被欺骗
2021-02-08 15:55:41
但这与“公开”任何其他 REST API 不一样吗?我的意思是用户可以使用 REST API URL。他们可以使用 URL 发出他们想要的任何请求并耗尽您的配额。firebase 所做的是使用带有 api 密钥的配置来识别您的后端部分,并且它必须可供用户发出请求。
2021-02-13 15:55:41
@forresthopkinsa 我有上面的链接评论采取什么方法。这里没有人天真到认为它是一个秘密密钥。
2021-02-21 15:55:41
@mbochynski 但您可以在某种程度上直接请求导致您支付账单的资源。在 Firebase 方面,没有那么多控制机制来防止 DDoS 攻击等。我的建议是让您的客户端调用您的 REST API,但 REST API 应该私下保存 API 密钥,甚至在您访问 Firebase 资源之前,验证它们如果它们是合法的请求。(通过 Cloudflare 等)。或从缓存中检索结果。然后,您只会在需要时才访问您的 Firebase 资源。这就是我要实现的firebase.google.com/docs/admin/setup
2021-02-25 15:55:41
你们考虑的不对。不要将 API Key 视为秘密;它不是私钥,它只是一个 ID,因此 Firebase API 知道谁在访问什么项目。如果您想要很大的灵活性并且需要控制服务器/客户端交互的每一步,那么您不应该使用 Firebase,而应该使用 GCP。
2021-03-09 15:55:41

当启用用户/密码注册时,API 密钥暴露会产生一个漏洞。有一个开放的 API 端点,它接受 API 密钥并允许任何人创建一个新的用户帐户。然后,他们可以使用这个新帐户登录受 Firebase 身份验证保护的应用程序,或使用 SDK 使用用户/密码进行身份验证并运行查询。

我已经向谷歌报告了这个,但他们说它按预期工作。

如果您不能禁用用户/密码帐户,您应该执行以下操作: 创建一个云功能以在创建时自动禁用新用户并创建一个新的数据库条目来管理他们的访问。

例如:MyUsers/{userId}/Access: 0

exports.addUser = functions.auth.user().onCreate(onAddUser);
exports.deleteUser = functions.auth.user().onDelete(onDeleteUser);

更新您的规则,只允许访问权限大于 1 的用户读取。

如果侦听器功能没有足够快地禁用帐户,则读取规则将阻止它们读取任何数据。

@VaibS火力地堡验证REST API firebase.google.com/docs/reference/rest/auth
2021-02-07 15:55:41
你说的是哪个 API?
2021-02-13 15:55:41
如果我们只将我们的域列入白名单,它仍然是一个问题吗?
2021-03-04 15:55:41

我相信一旦数据库规则写得准确,就足以保护您的数据。此外,还可以遵循一些准则来相应地构建您的数据库。比如在users下创建一个UID节点,把所有的信息放在它下面。之后,您将需要实现一个简单的数据库规则,如下所示

  "rules": {
    "users": {
      "$uid": {
        ".read": "auth != null && auth.uid == $uid",
        ".write": "auth != null && auth.uid == $uid"
      }
    }
  }
}

其他用户将无法读取其他用户的数据,而且域策略将限制来自其他域的请求。人们可以在Firebase 安全规则上阅读更多相关信息