GAE访问云存储API请求 - 403未配置访问权限
我的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 个回答
我把这个发出来作为一个回答,因为我之前的修改(我们是一起工作的)似乎被默默拒绝了,而评论的空间太有限。这不是一个答案,而是对问题的进一步解释。
这里有一个更简单的例子,只有一个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