尝试使用签名的URL上传到GCS时,获取403“匿名呼叫者没有storage.objects.get访问权限”

时间:2019-08-02 22:13:24

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

我正在尝试使用signed URLs将文件从浏览器直接上传到GCS。我正在从App Engine标准PHP应用程序生成一个v4签名的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>

我的App Engine服务帐户具有Service Account Token Creator,可用于创建URL。

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

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

我正在使用PHP Google Cloud Library生成签名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. 按照下面约翰的建议,我需要在服务帐户用户上添加Storage Object Creator。但是,它已经被添加到GAE默认服务帐户中,因为它是Project Editor
  3. Service Account Token Creator需要明确地添加到服务帐户,因为Project Editor似乎没有涵盖该帐户。
  4. 我使用Twig使用const url='{{ upload_url }}';将URL嵌入到Javascript中,但是Twig自动对变量进行HTML编码,从而破坏了URL,相反,我需要使用{{ upload_url|raw }}。这种格式损坏的原因是邮件中包含Anonymous caller

1 个答案:

答案 0 :(得分: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语言。