Firebase 存储安全规则和上传文件的下载令牌

cbd*_*per 8 firebase firebase-storage google-cloud-firestore

TLDR:这是一个关于从 返回的 URLtask.snapshot.ref.getDownloadURL()及其各自的downloadToken. 它询问 的主要作用和功能是什么,token以及是否需要根据安全规则公开的文件。


我刚刚完成了在https://firebase.google.com/docs/storage/web/upload-files以及来自 Firebase 官方频道的 Youtube 教程中找到的有关将文件上传和下载到 Firebase 存储的教程指南

我正在为我的一个 Firebase 网络应用程序(React + Firebase)中的博客部分构建一个内容管理系统。

我有一个组件,可让管理员选择图像并将其上传到 Firebase 存储桶以显示在特定的博客文章中。特定的所有图像blogPost都应位于特定blog-post-slug.

例子:

//bucket/some-blog-post-slug/image1.jpg
Run Code Online (Sandbox Code Playgroud)

每当管理员在 上选择新文件时运行的代码<input type='file'/>

function onFileSelect(e) {
  const file = e.target.files[0];
  const storageRef = firebase.storage().ref('some-slug/' + file.name);
  const task = storageRef.put(file);
  task.on('state_changed',
    function progress(snapshot) {
      setPercent((snapshot.bytesTransferred / snapshot.totalBytes) * 100);
    },
    function error(err) {
      console.log(err);
    },
    function complete() {
      console.log('Upload complete!');
      task.snapshot.ref.getDownloadURL().then(function(downloadURL) {
        console.log('File available at', downloadURL);
        props.changeImageSrc(downloadURL);
      });
    }
  );
}
Run Code Online (Sandbox Code Playgroud)

上面的代码返回downloadURL将保存到blogPost文档内 Firestore 的。

downloadURL格式如下:

https://firebasestorage.googleapis.com/v0/b/MYFIREBASEAPP.appspot.com/o/some-slug%2FILE_NAME.jpg?alt=media&token=TOKEN_VALUE

你可以看到它带有一个“基本 URL”: https://firebasestorage.googleapis.com/v0/b/MYFIREBASEAPP.appspot.com/o/some-slug%2FILE_NAME.jpg

并且basicURL附加有以下 GET 参数:

alt=mediatoken=TOKEN_VALUE

我不知道我会得到一个令牌,所以我现在正在测试它的行为以了解更多信息。


允许读取存储的行为:

service firebase.storage {
  match /b/{bucket}/o {
    match /{allPaths=**} {
      allow read, write;
}}}
Run Code Online (Sandbox Code Playgroud)
  • 当我访问 basicURL 时:
  • 我得到了一个对象,其中包含上传的文件详细信息:
{
  "name": "some-slug/FILE_NAME.jpg",
  "bucket": "MYBUCKET",
  "generation": "GENERATION_NUMBER",
  "metageneration": "1",
  "contentType": "image/jpeg",
  "timeCreated": "2019-06-05T13:53:57.070Z",
  "updated": "2019-06-05T13:53:57.070Z",
  "storageClass": "STANDARD",
  "size": "815155",
  "md5Hash": "Mj4aCPs21NUNxXpKg1bHirFIO0A==",
  "contentEncoding": "identity",
  "contentDisposition": "inline; filename*=utf-8''FILE_NAME.jpg",
  "crc32c": "zhkQMQ==",
  "etag": "CKu4a1+u2+0ucI412CEAE=",
  "downloadTokens": "TOKEN_VALUE"
}
Run Code Online (Sandbox Code Playgroud)
  • 当我访问 basicURL?alt=media
  • 显示图像。

  • 当我访问 basicURL?alt=media&token=TOKEN_VALUE

  • 显示图像。

存储读取受限的行为:

service firebase.storage {
  match /b/{bucket}/o {
    match /{allPaths=**} {
      allow read, write: if request.auth != null;
}}}
Run Code Online (Sandbox Code Playgroud)
  • 当我访问 basicURL 时:
  • 我得到以下错误对象:
{
  "error": {
    "code": 403,
    "message": "Permission denied. Could not perform this operation"
  }
}
Run Code Online (Sandbox Code Playgroud)
  • 当我访问 basicURL?alt=media
  • 我得到相同的错误对象:
{
  "error": {
    "code": 403,
    "message": "Permission denied. Could not perform this operation"
  }
}
Run Code Online (Sandbox Code Playgroud)
  • 当我访问 basicURL?alt=media&token=TOKEN_VALUE
  • 显示图像。

结论和问题

在我看来,安全规则allow read: if request.auth != null;应该阻止未经授权用户的任何读取,但是使用该TOKEN参数,即使对于没有auth对象的请求,该文件也可以访问(注意:运行上述测试时我没有登录)。

我知道提出 1 个以上的问题不是最佳做法,但在这种情况下,我认为有必要:

问题 1:

这个 TOKEN 的主要用途是什么,为什么它会凌驾于auth规则之上?

问题2:

我希望这些图片可以公开使用,因为博客部分将供所有用户使用。我应该将哪个 URL 保存到 Firestore?

  • 选项 1:允许所有人读取并只保存 basicURL。

  • 选项 2:限制读取并保存 basicURL + 令牌。

问题 3:

要在<image src="imgSrc">标签中显示图像,我需要alt=media参数吗?还是以 FILE_NAME 结尾的 basicURL 就足够了?

编辑:问题 3 答案:刚刚测试它并发现alt=mediaGET 参数对于在<img>标签内显示图像是必要的。


注意:如果您上传相同的文件并替换旧文件,则token每次都会得到不同的文件,旧文件token将失效。

小智 -1

    service firebase.storage {
      match /b/{bucket}/o {
        match /{allPaths=**} {
          allow read, write;
        }
      }
    }
Run Code Online (Sandbox Code Playgroud)

这是 Firebase 存储的安全权限。所有类型的数据(图像、视频等)