【问题标题】:Getting 403 "Anonymous caller does not have storage.objects.get access" when trying to upload to GCS with signed URLs尝试使用签名 URL 上传到 GCS 时出现 403“匿名调用者没有 storage.objects.get 访问权限”
【发布时间】:2019-12-11 12:35:31
【问题描述】:

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

<?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>

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

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

我已从 v2 网址切换到 v4,因为 Go SDK 上的问题表明这是一个问题。

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

$storage = new StorageClient();
$bucket = $storage->bucket('<bucket-name>');
$object = $bucket->object('some-object.txt');

$url = $object->signedUploadUrl(new \DateTime('tomorrow'), ['version' => 'v4']);

我尝试将服务帐户添加到存储桶的权限并添加Storage Object AdminStorage Object Creator 等,但似乎没有什么能让我超过这个403(除了打开它到allUsers)。

this文章中说

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

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

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

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

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

已解决:

我的实现有很多问题:

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

【问题讨论】:

  • 几个问题/建议:生成的 URL 是什么样的?您是在使用 POST 来启动使用该 URL 的可恢复上传,还是尝试直接将数据上传到提供的 URL?如果是后者,您可能想改用beginSignedUploadSession
  • @BrandonYarbrough 我直接对 URL 执行 PUT,我尝试了 signedUploadUrlbeginSignedUploadSession,两种情况下的错误都是一样的。
  • @BrandonYarbrough URL 太长,无法在此处发布,因此我已将其放在 pastbin
  • 出现错误表示您用于创建签名 URL 的身份没有storage.objects.create 将 Cloud Storage 角色添加到用于创建签名 URL 的服务帐户。
  • @JohnHanley 我已将Storage Object Creator 添加到应用引擎服务帐户和服务帐户对存储桶的权限,遗憾的是我仍然遇到相同的错误。

标签: google-app-engine google-cloud-platform google-cloud-storage google-cloud-iam


【解决方案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 写给我的。

【讨论】:

  • 我现在转移到 beginSignedUploadSession(),它应该允许直接的 PUT 请求,它给出了同样的错误。
  • @tomphp 我知道已经有一段时间了,但你是怎么解决的?
  • 我遇到了完全相同的问题,这是因为签名的 url 没有正确编码。
猜你喜欢
  • 1970-01-01
  • 2019-10-11
  • 2020-09-23
  • 2020-12-16
  • 1970-01-01
  • 1970-01-01
  • 2022-01-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多