尝试使用签名 URL 上传到 GCS 时出现 403“匿名调用者没有 storage.objects.get 访问权限”

tom*_*php 5 google-app-engine google-cloud-storage google-cloud-platform google-cloud-iam

我正在尝试使用签名 URL将文件直接从浏览器上传到 GCS 。我正在v4从 App Engine 标准 PHP 应用程序生成签名 URL,这似乎工作正常。问题是当我尝试访问PUT该 URL 时,我得到了403以下 XML 响应:

<?xml version='1.0' encoding='UTF-8'?>
<Error>
  <Code>AccessDenied</Code>
  <Message>Access denied.</Message>
  <Details>Anonymous caller does not have storage.objects.create access to <bucket-name>/some-object.txt.</Details>
</Error>
Run Code Online (Sandbox Code Playgroud)

我的应用程序引擎服务帐户具有Service Account Token Creator,它允许创建 URL。

我已启用存储桶上的 CORS 以接受PUTto *,这使我能够到达现在的位置。

我已经从v2URL切换到v4Go SDK 上的一个问题,这表明这是一个问题。

我正在使用 PHP Google Cloud Library 生成签名 URL,如下所示:

<?xml version='1.0' encoding='UTF-8'?>
<Error>
  <Code>AccessDenied</Code>
  <Message>Access denied.</Message>
  <Details>Anonymous caller does not have storage.objects.create access to <bucket-name>/some-object.txt.</Details>
</Error>
Run Code Online (Sandbox Code Playgroud)

我已经尝试将服务帐户添加到存储桶的权限并添加Storage Object Admin,Storage Object Creator等,但似乎没有什么能让我克服这一点403(除了将其打开到allUsers)。

这篇文章中说

此外,在 Cloud Storage 中,您需要授予以下权限以生成签名 URL。

  • storage.buckets.get
  • storage.objects.create
  • storage.objects.delete

但我就是不知道他们需要添加到哪个角色。

在这一点上,我认为有两种可能性之一:

  1. 签名的 URL 实际上不起作用,因为它应该作为服务帐户而不是匿名进行身份验证。在这种情况下,什么可能导致这种情况?
  2. 签名 URL 作为某种类型的匿名角色进行身份验证,但该角色没有权限。在这种情况下,如何为该角色添加权限(allUsers显然是错误的)?

解决了:

我的实现有很多问题:

  1. 正如下面 Brandon & Charles 所建议的,signedUploadUrl不适合直接PUT. 为了解决这个问题,我需要使用beginSignedUploadSession
  2. 正如下面约翰所建议的,我需要Storage Object Creator添加服务帐户用户。但是,这已经添加到 GAE 默认服务帐户中,因为它是Project Editor
  3. Service Account Token Creator需要明确添加到服务帐户,因为Project Editor似乎没有涵盖它。
  4. 我使用 Twig uses 将 URL 嵌入到 Javascript 中const url='{{ upload_url }}';,但是 Twig 会自动对变量进行 HTML 编码,因此破坏了 URL,相反,我需要使用{{ upload_url|raw }}. 这种损坏的格式是消息包含的原因Anonymous caller

Cha*_*lke 1

signedUploadUrl为 POST HTTP 方法创建 URL(请参阅https://github.com/googleapis/google-cloud-php/blob/master/Storage/src/StorageObject.php上的库源代码)。您正在使用该签名 URL 进行 PUT 请求,因此不允许该请求。错误消息并未表明这是问题所在,但我认为这就是问题所在。

您可以了解如何通过 POST 上传文件,或者为 PUT 创建签名 URL。我已经用 Python 完成了后者,但我没有找到使用这个库来完成此操作的方法。我不是 PHP 程序员,所以我可能会错过它。

或者,您可以创建自己的代码来为 PUT 创建签名 URL,以库代码为例。要获得完全正确的签名 URL 极其困难,并且创建自己的代码可能会令人沮丧。这是给我用 Python 的。