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

Firebase网络应用指南表示我应该将给定的apiKey放在我的Html中以初始化Firebase:

// 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暴露给每个访问者。

什么是该密钥的目的,它真的是应该是公开的吗?

211874 次浏览

此配置片段中的apiKey只是标识您在Google服务器上的Firebase项目。别人知道并不存在安全风险。事实上,他们有必要知道这一点,以便他们与您的Firebase项目进行交互。每个使用Firebase作为后端的iOS和Android应用中也会包含相同的配置数据。

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

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

有关Firebase使用这些值的其他说明,以及可以为其中哪些设置配额,请参阅使用和管理API密钥上的Firebase留档。


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


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

您通常希望将其与上述基于用户身份验证的安全性相结合,以便您有另一个保护来抵御使用您的应用程序的滥用用户。

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

基于pruFrofro和Frank van 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 Key,它将是私有的,用于localhost开发。

  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,
// ...
};

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

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

我更希望客户端首先攻击您的Web服务器,在那里您可以在客户端和服务器之间或服务器和Firebase之间放置第一手防火墙、验证码、Cloudflare、自定义安全性,您就可以开始了。至少您可以在可疑活动到达Firebase之前首先阻止它。您将有更大的灵活性。

我只看到一个很好的使用场景,用于内部使用基于客户端的配置。例如,你有内部域,你很确定外部人员无法访问那里,所以你可以设置浏览器->Firebase类型这样的环境。

启用用户/密码注册时,API密钥暴露会创建漏洞。存在一个接受API密钥并允许任何人创建新用户帐户的开放API终结点。然后,他们可以使用此新帐户登录到受Firebase Auth保护的应用,或使用SDK对用户/通行证进行身份验证并运行查询。

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

如果您无法禁用用户/密码帐户,您应该执行以下操作: 创建一个云函数来自动禁用新用户onCreate并创建一个新的数据库条目来管理他们的访问权限。

例如:我的用户/{userId}/访问权限: 0

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

更新您的规则以仅允许访问权限>1的用户读取。

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

我相信一旦数据库规则写得准确,就足以保护你的数据。此外,在构建数据库时也有一些指导方针可以遵循。例如,在用户下面创建一个UID节点,并将所有信息放在它下面。之后,你需要实现一个简单的数据库规则,如下所示

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

没有其他用户能够读取其他用户的数据,此外,域策略将限制来自其他域的请求。 人们可以在上面阅读更多关于它的信息 Firebase安全规则

虽然最初的问题得到了回答(api键可以暴露-数据的保护必须从数据库规则中设置),但我也在寻找一种解决方案来限制对数据库特定部分的访问。 因此,在阅读了这篇文章和一些关于可能性的个人研究之后,我想出了一种稍微不同的方法来限制未经授权用户的数据使用:

我也将我的用户保存在我的数据库中,在同一个uid下(并将配置文件数据保存在那里)。所以我只是像这样设置数据库规则:

".read": "auth != null && root.child('/userdata/'+auth.uid+'/userRole').exists()",
".write": "auth != null && root.child('/userdata/'+auth.uid+'/userRole').exists()"

这样,只有以前保存的用户才能在数据库中添加新用户,因此没有帐户的任何人都无法在DB上进行操作。

此外,只有当用户具有特殊角色并且仅由管理员或该用户本身编辑时,才可以添加新用户(如下所示):

"userdata": {
"$userId": {
".write": "$userId === auth.uid || root.child('/userdata/'+auth.uid+'/userRole').val() === 'superadmin'",
...

您不应该公开此信息。在公共场合,特别是api密钥。 这可能会导致隐私泄露。

在公开网站之前,您应该隐藏它。您可以通过两种或多种方式做到这一点

  1. 复杂编码/隐藏
  2. 只需将Firebase SDK代码放在您的网站或应用程序的底部,因此Firebase会自动完成所有工作。你不需要把API密钥放在任何地方

暴露API密钥不是安全风险,但任何人都可以将您的证书放在他们的网站上。

打开api密钥会导致攻击,这些攻击可以使用Firebase上的大量资源,这肯定会花费您的辛苦钱。

您始终可以将Firebase项目密钥限制为域/IP。

https://console.cloud.google.com/apis/credentials/key

选择您的项目ID和密钥并将其限制为您的Android/iOS/Web应用程序。

我正在github页面上制作一个博客网站。我有一个想法,在每个博客页面的末尾嵌入评论。我了解Firebase如何获取并为您提供数据。

我已经用项目甚至使用控制台测试了很多次。我完全不同意vlight易受攻击的说法。 相信我,如果您遵循了Firebase推荐的隐私步骤,公开显示您的api密钥是没有问题的。 转到https://console.developers.google.com/apis #36825;的安全措施

可以包含它们,并且仅对Firebase ML或使用Firebase身份验证时需要特别注意

Firebase的API密钥不同于典型的API密钥: 与通常使用API密钥的方式不同,Firebase服务的API密钥不用于控制对后端资源的访问;这只能通过Firebase安全规则来完成。通常,您需要严格保护API密钥(例如,通过使用保管库服务或将密钥设置为环境变量);但是,Firebase服务的API密钥可以包含在代码或签入配置文件中。

尽管在代码中包含Firebase服务的API密钥是安全的,但在某些特定情况下,您应该对API密钥强制执行限制;例如,如果您使用Firebase ML或通过电子邮件/密码登录方法使用Firebase身份验证。稍后在本页了解有关这些情况的更多信息。

有关更多信息,请查看官方文档