Firebase Web-App指南指出,我应该把给定的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就暴露给了每个访问者。

这个密钥的目的是什么?它真的是要公开的吗?


当前回答

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

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

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

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

此外,只有当用户具有特殊角色并且只能由管理员或该用户自己编辑时,才可以添加新用户(就像这样):

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

其他回答

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

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

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

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

此外,只有当用户具有特殊角色并且只能由管理员或该用户自己编辑时,才可以添加新用户(就像这样):

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

根据prufrofro和Frank van Puffelen的回答,我将这个设置组合在一起,它不能防止刮取,但可以略微增加使用API密钥的难度。

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

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

只有数据库安全规则可以保护您的数据。

然而,我限制我的生产API密钥使用我的域名,像这样:

https://console.developers.google.com/apis 选择您的Firebase项目 凭证 在API键下,选择浏览器键。它应该看起来像这样:“浏览器键(由谷歌服务自动创建)” 在“Accept requests from these . HTTP引用者(网站)”,添加你的应用的URL(例如:projectname.firebaseapp.com/*)

现在该应用程序将只工作在这个特定的域名。因此,我创建了另一个API密钥,将是私有的本地主机开发。

单击“创建凭据> API密钥”

默认情况下,如Emmanuel Campos所述,Firebase只将本地主机和您的Firebase托管域列入白名单。


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

创建-反应-应用程序的设置

在/ 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服务器,在那里你把任何第一手的防火墙,验证码,cloudflare,自定义安全在客户端和服务器之间,或服务器和firebase之间,你就好了。至少你可以在可疑活动到达火源之前阻止它。你会有更大的灵活性。

在内部使用基于客户端的配置时,我只看到一个好的使用场景。例如,您有一个内部域,并且您非常确定外部人员无法访问该域,因此您可以设置类似浏览器-> firebase类型的环境。

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

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

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

Ex: MyUsers/ (userId) /Access: 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安全规则