首页 > 解决方案 > 验证 Firebase 实时 URL 是否来自 Firebase 存储

问题描述

所以我在我的网站上有一个功能,允许用户上传个人资料照片。照片存储在我的 Firebase 存储中的 UID 下的文件夹中,然后成功上传后,downloadURL 将存储在我的 Firebase 实时数据库中的 UID 下,如下所示:

database.ref('users/'+firebase.auth().currentUser.uid).update({
profilePhoto: downloadURL
});

现在我已经制定了一些规则,以便只有身份验证 UID 可以将数据写入自己。

{
"rules": { 
 "users": {
  ".read": "true",
  "$user": {
   ".read": "true",
   ".write": "auth.uid == $user",
    "profilePhoto": {
     ".validate": "newData.isString()
    },  
  }
 }
}
}

工作得很好,但我怎样才能让它只写直接来自我的 Firebase 存储的 URL?

例如,有知识的用户可以简单地运行上面的脚本并将数据更改为存储之外的内容,或者只是一些随机文本,当我获取它时会破坏配置文件图像。

我想做的一件事是添加 Firebase 存储“基本路径”作为验证,如下所示:

"profilePhoto": {
 ".validate": "newData.isString()
 && newData.val().contains('mystorage-12345.appspot.com/') 
}

但是有没有更好的方法呢?“基本路径”会改变吗?

标签: javascriptjqueryfirebase

解决方案


没有可用于防止用户链接到恶意文件或输入乱码的规则组合。由于您愿意接受更好的方法,因此这是我处理此类上传的标准模式。

首先,确定您的个人资料照片的 URL 结构,照片将以易于猜测的格式存储在您的存储桶中。我的偏好是: /u/<uid>/profile_<width>x<height>.jpg

其次,为您的用户提供一个签名的 URL 以将他们的图像上传到。这可能在一个单独的存储桶中,当出现新对象时,会触发调整照片大小的函数,然后将调整大小的照片移动到/u/<uid>/profile_<width>x<height>.jpg相关的宽度和高度。

最后,无需存储个人资料照片的 URL,因为任何用户的个人资料都可以这样显示:

<img src="https://<bucketUrl>/u/<uid>/profile_512x512.jpg" onerror="this.src=' + "/img/default-profile.jpg" + '" />

这里发生的事情是它首先尝试使用可猜测的模式加载用户的个人资料照片,如果由于任何/u/<uid>/profile_<width>x<height>.jpg原因无法加载,则在其位置显示默认照片。

优点

  1. 由于更少的数据库读取、写入和存储而降低了成本。
  2. 简单、快速、可靠。
  3. 内置故障转移,以防因任何原因无法访问存储桶。

推荐阅读