GAE访问云存储API请求 - 403未配置访问权限

3 投票
1 回答
2032 浏览
提问于 2025-04-18 10:30

我的GAE应用程序正在尝试处理存储在Google Cloud Storage上的文件。

这些文件存储在我应用的默认存储桶里。我已经成功使用GCS Python客户端库读取和写入这个存储桶中的文件(https://developers.google.com/appengine/docs/python/googlecloudstorageclient/)。

可惜的是,这个库不支持复制文件。因此,我尝试使用JSON API和API客户端库(https://google-api-client-libraries.appspot.com/documentation/storage/v1/python/latest/storage_v1.objects.html)以及服务账户(https://developers.google.com/api-client-library/python/guide/google_app_engine#ServiceAccounts)。

到目前为止,当我请求云存储的URL时,出现了403错误。

这是我的代码:

credentials = AppAssertionCredentials(scope='https://www.googleapis.com/auth/devstorage.read_write')
http = credentials.authorize(httplib2.Http(memcache))
service = discovery.build('storage', 'v1', http=http, developerKey='api_key_generated_from_the_dev_console')
bucket_name = app_identity.get_default_gcs_bucket_name()

# I'm planning to batch multiple requests, although there is just one in this example
batch = BatchHttpRequest()

# process_list_response outputs the exception if any
batch.add(service.objects().list(bucket=bucket_name), callback=process_list_response) 
batch.execute(http=http)

这是日志信息:

请求的URL: https://www.googleapis.com/discovery/v1/apis/storage/v1/rest?userIp=x.x.x.x

尝试刷新以获取初始的access_token

请求的URL: https://www.googleapis.com/storage/v1/b/xxx.appspot.com/o?alt=json

请求时出现HttpError 403 https://www.googleapis.com/storage/v1/b/xxx-dev.appspot.com/o?alt=json 返回了"访问未配置。请使用Google开发者控制台为您的项目激活API。"

这是我在开发者控制台做的设置:

  • Google Cloud Storage和Google Cloud Storage JSON API已经开启。
  • 我创建了一个API密钥,用于构建服务(因为我也使用Oauth,这个是必要的吗?)
  • 在权限设置中,我为我的应用添加了一个成员,邮箱是xxx@appspot.gserviceaccount.com。

我该如何让这个工作正常?

1 个回答

2

我把这个发出来作为一个回答,因为我之前的修改(我们是一起工作的)似乎被默默拒绝了,而评论的空间太有限。这不是一个答案,而是对问题的进一步解释。

这里有一个更简单的例子,只有一个http请求。看起来JSON API在API探索器之外根本无法使用。XML/REST API可以正常工作,并返回存储桶中的文件列表。

credentials = AppAssertionCredentials(scope='https://www.googleapis.com/auth/devstorage.read_write')
http = credentials.authorize(httplib2.Http(memcache))

bucket_name = app_identity.get_default_gcs_bucket_name()

# This works (200 with list of files in the content)
request_url = 'http://commondatastorage.googleapis.com/' + bucket_name
response, content = http.request(request_url, method="GET")

# This doesn't work (403, Access not configured)
request_url = 'https://www.googleapis.com/storage/v1/b/' + bucket_name + '/o?alt=json'
response, content = http.request(request_url, method="GET")

# This doesn't work (403, Access not configured), the key and project id header seem useless.
request_url = 'https://www.googleapis.com/storage/v1/b/' + bucket_name + '/o?alt=json&key=' + API_KEY
response, content = http.request(request_url, method="GET", headers={'x-goog-project-id': PROJECT_ID})

另外,看看AppAssertionCredentials的代码,我们可以看到:

  kwargs: optional keyword args, including:
    service_account_id: service account id of the application. If None or
      unspecified, the default service account for the app is used.

self.service_account_id = kwargs.get('service_account_id', None)

传递任何东西作为service_account_id参数都会导致异常:

Traceback (most recent call last):
  File "/base/data/home/apps/.../1.37.../backup.py", line 61, in get
    response, content = http.request(request_url, method="GET")
  File "/base/data/home/apps/.../1.377.../oauth2client/util.py", line 132, in positional_wrapper
    return wrapped(*args, **kwargs)
  File "/base/data/home/apps/.../1.37.../oauth2client/client.py", line 491, in new_request
    self._refresh(request_orig)
  File "/base/data/home/apps/.../1.37.../oauth2client/appengine.py", line 197, in _refresh
    raise AccessTokenRefreshError(str(e))
AccessTokenRefreshError

我尝试传递app_identity.get_service_account_name()返回的值,但这也不行。(尽管文档上说如果没有设置,它会使用"应用的默认服务账户"。)

我还尝试传递在开发者控制台找到的服务账户邮箱,格式是:3....-v0....@developer.gserviceaccount.com。结果也是同样的令牌异常。

那么,为什么当我们的Cloudstorage JSON API明显已经在api/services下启用时,仍然会出现403访问未配置的错误呢?

而且为什么将service_account_id传递给AppAssertionCredentials会导致AccessTokenRefreshError错误呢?

补充:

解决方案真是让人哭笑不得:关闭Google Cloud Storage API,然后再打开它。

我猜这个应用是一个“遗留”应用,做这个操作后,最后一点12在这里就能正常工作了:https://developers.google.com/appengine/docs/python/googlecloudstorageclient/activate

撰写回答