【问题标题】:Firebase Storage Rules Private URL for authenticated users (without downloadURL or library)Firebase 存储规则 经过身份验证的用户的私有 URL(没有 downloadURL 或库)
【发布时间】:2023-03-21 22:18:01
【问题描述】:

是否可以在不使用getDownloadURL@firebase/storage 库的情况下私​​下在我的Web 应用程序中显示图像(<img/>)?

例如我尝试了以下规则:

rules_version = '2';

service firebase.storage {
  match /b/{bucket}/o {
    match /{userId}/images/{allPaths=**} {
      allow write: if request.auth.uid == userId;
      allow read: if request.auth.uid == userId;
    }
  }
}

我的 html 页面包含如下图像:

<img src="https://firebasestorage.googleapis.com/v0/b/{projectId}.appspot.com/o/{userId}/images/yolo.jpg?alt=media/>

此页面仅显示给经过身份验证的用户,但即使在成功登录后,当我尝试呈现上面显示的图像时,我仍然会收到 403

我的猜测是 img https 请求不包含任何有关授权的信息,这就是它失败的原因。

因此我的问题是,有没有办法在不使用 Firebase 库下载图像/文件的情况下获取私有存储文件?

【问题讨论】:

  • 您的 Web 应用程序是否在云中运行?如果没有,为什么不能只使用服务器本地磁盘中的图像并编写一些身份验证逻辑来​​提供图像?
  • 感谢您的回复。应用程序在客户端运行,并且“我必须”将其从图像标签链接起来,因为 html 内容是由用户编辑的某个扩展名。
  • 整个应用程序都在运行客户端,包括服务器/后端?我认为这些图像也是动态上传的,或者这些只是您想要显示但仅限于某些经过身份验证的用户的静态图像?您可以尝试在 AJAX/fetch 中请求图像数据,并将 &lt;img&gt; 标记的源设置为您从获取图像时生成的 Base64 编码二进制数据 URI,这样您就可以完全控制发送来检索它的标头/cookie。
  • 再次感谢。不幸的是,我不能真正通过 Ajax 进行查询,它必须是某种给定的静态图像标签(当然复杂性不同,但这是我可以缩小要求的方式)。
  • 我认为没有任何易于访问的 URL 可以有效地“编码”其中可以在安全规则中检查的身份验证权限。我相信您可以想象这样的安全问题,即在它们打算使用的时间和空间之外共享这些 URL 的可能性。

标签: javascript firebase firebase-authentication firebase-storage firebase-security


【解决方案1】:

正如我的问题 NO 的 cmets 部分所述,如果不通过客户端请求获取图像,就无法实现我的目标。

但是,我设法找到了适合我们应用程序需求的解决方案,因此让我分享一下。

首先,更多内容。我们应用程序的内容是一个所见即所得的演示编辑器,由用户生成,并且在稍后阶段也可能被公开共享。这就是为什么我们需要拥有私有和公共资产。

此外,共享内容是 HTML,也是用户正在编辑的内容,因此它不是,或者至少对我来说不是,直接附加请求以获取图像。

幸运的是,我们确实使用了 Web 组件,多亏了阴影内容,我可以在图像公开时混淆我不需要的内容。

分别地,在这种情况下,我没有使用&lt;img/&gt;元素,而是使用了我们的组件&lt;deckgo-lazy-img/&gt;

npm install @deckdeckgo/lazy-img

这就是我改进组件并添加新的boolean 属性custom-loader 的原因。当切换到true 时,该组件不会在与视口相交时显示图像,而是会冒泡一个事件custom-load,可以拦截该事件以便使用自定义代码加载图像。

因此,我只需添加以在我的应用程序中查找我的 components 元素并将该属性设置为 true。还需要注意的好事情是,属性没有反映在 dom 中,因此我最初的问题已经解决了,因为用户的内容不会改变。

html:

<deckgo-lazy-img img-src='https://firebasestorage..'/>

javascript:

document.querySelector('deckgo-lazy-img').customLoader = true;

最后,我添加了一个事件监听器来拦截自定义事件:

document.addEventListener('customLoad', this.onCustomLoad, false);

自定义甚至提供信息imgElement(阴影图像)和imgSrc(作为组件属性提供的图像的实际来源)。

然后使用 Firebase 存储处理图像的加载,同时使用登录用户的令牌对请求进行身份验证,因为我想保留上述规则。

try {
  const rawResponse: Response = await fetch(detail.imgSrc, {
    method: 'GET',
    headers: {
      'Authorization': `Bearer ${your_user_auth_token}`
    }
  });

  if (!rawResponse || !rawResponse.ok) {
    console.error(`Image ${detail.imgSrc} can not be fetched.`);
    return;
  }

  const blob: Blob = await rawResponse.blob();
  detail.imgElement.src = URL.createObjectURL(blob);
} catch (err) {
  console.error(err);
}

(其中detail 是自定义事件详细信息)。

我们的项目是开源的,这里是相关的commit我添加到我正在处理的 PR 中。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-03-31
    • 1970-01-01
    • 2018-10-10
    • 2016-10-17
    • 2021-10-14
    • 2019-03-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多