从 Flutter Web 应用程序发送 Firebase 存储授权作为 url 参数
Posted
技术标签:
【中文标题】从 Flutter Web 应用程序发送 Firebase 存储授权作为 url 参数【英文标题】:Send firebase storage authorization as url parameter from a flutter web app 【发布时间】:2020-10-13 21:32:07 【问题描述】:我想知道如何使用用户 ID 令牌作为 url 中的参数向 Firebase 存储发出授权请求。现在使用“request.auth!= null”的firebase规则,我收到403网络错误(无法加载视频:您无权访问所请求的资源)。这是我的 GET 请求网址:
https://firebasestorage.googleapis.com/v0/b/<bucket>/o/<folder_name>%2F<video_name>.mp4?alt=media&auth=eyJh...<ID TOKEN>...Ll2un8ng
-在没有 firebase 规则的情况下,我可以通过此请求 url https://firebasestorage.googleapis.com/v0/b/<bucket>/o/<folder_name>%2F<video_name>.mp4?alt=media
成功获取资产
-也尝试过 token=、token_id=、tokenId=
-不使用 firebase SDK 来获取文件的原因是我可以使用 flutter video_player (https://pub.dev/packages/video_player#-example-tab-) 包并将其与 firebase 中的文件一起使用,如果有更好的使用方法,我会提到这一点现在 Flutter Web 中的 video_player 库:
_controller = VideoPlayerController.network(
'https://flutter.github.io/assets-for-api-docs/assets/videos/bee.mp4',
closedCaptionFile: _loadCaptions(),
);
[编辑] 似乎无法将身份验证作为查询参数传递。经过一番探索,我找到了一种可接受的方式,仍然可以将 video_player 与受保护的 firebase 资产一起使用(如果您不使用规则来保护它们,则可以直接使用 firebase url)。我将在这里发布一些一般步骤和一些示例代码:
使用Storage Firebase SDK包获取Uint8List,getDownloadURL给出的uri有正确的header auth,例如
import 'package:firebase/firebase.dart';
final url = await storagePath.getDownloadURL();
final response = await http.get(url);
if (response.statusCode == 200)
return response.bodyBytes;
使用 Uint8List 缓冲区初始化一个 Blob 对象,然后您将使用该对象创建一个 ObjectURL,它基本上为您提供与文件 url 相同的界面,用作视频播放器的网络 url
final blob = html.Blob([data.buffer], 'video/mp4');
final videoUrl = html.Url.createObjectUrl(blob);
videoPlayerController = VideoPlayerController.network(
videoUrl)
..initialize().then((_) ...
就是这样。
【问题讨论】:
在 URL 中包含 auth 令牌或 id 令牌确实是个坏主意。我建议您通过Authorization
标头或 POST 正文发送 id 令牌。
视频播放器包不支持标头 (github.com/flutter/flutter/issues/16466),正在寻找其他选项。感谢您的意见。
Firebase 存储似乎不支持通过 URL 中的 GET 查询字符串进行授权。您必须以某种方式传递标头(可能使用其他包/库)cloud.google.com/storage/docs/authentication#apiauth(是的,Firebase 存储使用 Google Cloud 存储,因此此链接是有效参考)
【参考方案1】:
在内部,这个包为flutter-web所做的所有事情都是创建一个HtmlElementView
小部件here,它从包dart:html
中传递一个VideoElement
(参考here),提供的URL转换为<Video>
标记在您的网页中的影子 dom 元素内。错误 403 也可能意味着您正在尝试从不同的来源访问它。
我建议采用以下方法。
检查您的控制台是否有任何与 CORS 相关的错误。如果是,那么您将不得不在 Firebase 存储中将您的 ip/域列入白名单。检查此post 以了解可能的方法和更多详细信息here。
检查您是否能够按照您的建议使用授权令牌作为查询参数直接访问 URL。如果不是,那么它不是访问对象的正确方法,应该更正。您可以使用确切的错误详细信息更新问题。
【讨论】:
不是 Cors,是权限错误。我可以像这样使用firebase sdk访问url(最终url = await firebasePath.child(filename).getDownloadURL(); final response = await http.get(url); )但是视频播放器需要1。文件,2. NetworkUrl(不接受标头)或 3. 资产。并且不接受原始数据(如 UInt8List),这使得在这种情况下很难使用 firebase sdk。我想我接下来会考虑使用 Indexeddb 和 ObjectURL,看看我的选择。感谢有关 VideoElement 的 cmets,这很有帮助!【参考方案2】:Firebase 存储 REST 不(正确地)支持来自 GET 查询字符串的授权,就像您尝试做的那样。相反,它使用标准的Authorization
标头(请参阅here)。
Firebase 云存储在内部使用 Google Cloud Storage。 Mentioned here
如果您使用的库还不支持 HTTP 标头,您必须考虑替代方案。您在评论中提到的问题表明该功能仍在开发中,因此您也可以等待库推出对标头的支持。
【讨论】:
这似乎是正确的,Firebase 存储不支持来自查询字符串的身份验证,如果有人遇到此问题,并且有办法做到这一点,请纠正我。我确实找到了一个有趣的解决方案来继续使用 video_player 包,我将发布它作为我的问题的编辑。然而,这个包确实是一个正在进行的工作,所以请注意这篇文章的日期,如果事情发生变化,我会尝试在这里发布更新。以上是关于从 Flutter Web 应用程序发送 Firebase 存储授权作为 url 参数的主要内容,如果未能解决你的问题,请参考以下文章
从 Flutter Web 应用程序发送 Firebase 存储授权作为 url 参数
如何通过使用flutter bloc从fire存储中使用依赖注入来处理错误`The getter was called on null`
Map in Flutter for Web - 将数据从 JS 发送到 Flutter for Web