python - 使用 Python 对 Google Storage 进行身份验证

标签 python google-oauth google-cloud-storage boto

我想构建一个可以与谷歌存储轻松交互的应用程序,即列出存储桶中的文件、下载文件和上传文件。

正在关注 this tutorial ,我决定使用服务帐户(不是用户帐户)进行身份验证并遵循该程序。我在我的控制台上创建了一个公钥/私钥,并在我的机器上下载了该 key 。然后我创建了指向这个私钥的 .boto 文件,最后启动了这个程序并且它成功了:

import boto
import gcs_oauth2_boto_plugin


uri = boto.storage_uri('txxxxxxxxxxxxxx9.appspot.com', 'gs')

for obj in uri.get_bucket():
  print '%s://%s/%s' % (uri.scheme, uri.bucket_name, obj.name)

如您所见,代码中未使用包gcs_oauth2_boto_plugin,所以我决定去掉它。但神奇的是,当我评论 import gcs_oauth2_boto_plugin 行并再次运行该程序时,我得到了这个错误:

C:\Users\...\Anaconda3\envs\snakes\python.exe C:/Users/.../Dropbox/Prog/s3_manifest_builder/test.py
Traceback (most recent call last):
  File "C:/Users/.../Dropbox/Prog/s3_manifest_builder/test.py", line 10, in <module>
    for obj in uri.get_bucket():
  File "C:\Users\...\Anaconda3\envs\snakes\lib\site-packages\boto\storage_uri.py", line 181, in get_bucket
    conn = self.connect()
  File "C:\Users\...\Anaconda3\envs\snakes\lib\site-packages\boto\storage_uri.py", line 140, in connect
    **connection_args)
  File "C:\Users\...\Anaconda3\envs\snakes\lib\site-packages\boto\gs\connection.py", line 47, in __init__
    suppress_consec_slashes=suppress_consec_slashes)
  File "C:\Users\...\Anaconda3\envs\snakes\lib\site-packages\boto\s3\connection.py", line 190, in __init__
    validate_certs=validate_certs, profile_name=profile_name)
  File "C:\Users\...\Anaconda3\envs\snakes\lib\site-packages\boto\connection.py", line 569, in __init__
    host, config, self.provider, self._required_auth_capability())
  File "C:\Users\...\Anaconda3\envs\snakes\lib\site-packages\boto\auth.py", line 987, in get_auth_handler
    'Check your credentials' % (len(names), str(names)))
boto.exception.NoAuthHandlerFound: No handler was ready to authenticate. 1 handlers were checked. ['HmacAuthV1Handler'] Check your credentials

所以我的问题是:

1- 你如何解释删除代码中未使用的导入会导致失败?

2- 更一般地说,为了确保了解身份验证过程,如果我想在机器上运行我的应用程序,我必须确保之前生成了 .boto 文件(指向我的服务帐户私钥) ?或者是否有一种更简洁/更简单的方法来将我的应用程序访问权限授予 Google Storage 以进行输入/输出交互?

例如,当我想使用 boto 连接到 S3 存储桶时,我只需将公钥和私钥作为字符串提供给我的程序。我不需要生成 .boto 文件、导入包等...,这使得它更易于使用,不是吗?

最佳答案

1- how can you explain that deleting an import which IS NOT USED in the code makes it fail?

第一个提示是该模块被命名为“插件”,尽管表面上并不清楚具体是如何实现的。不过,从直觉上讲,不导入模块会导致此类异常。最初,我认为在导入该模块的 init 期间对全局执行有状态事件是一种不好的做法。在某些方面,它就是这样,但这只是因为类层次结构在元可编程 python 中是“状态”。

事实证明(在许多情况下)检查堆栈跟踪的抛出位置 (boto.auth.get_auth_handler()) 提供了理解问题的关键。

(查看评论版本的链接源)

def get_auth_handler(host, config, provider, requested_capability=None):
    ready_handlers = []
    auth_handlers = boto.plugin.get_plugin(AuthHandler, requested_capability)
    for handler in auth_handlers:
        try:
            ready_handlers.append(handler(host, config, provider))
        except boto.auth_handler.NotReadyToAuthenticate:
            pass

    if not ready_handlers:
        checked_handlers = auth_handlers
        names = [handler.__name__ for handler in checked_handlers]
        raise boto.exception.NoAuthHandlerFound(
            'No handler was ready to authenticate. %d handlers were checked.'
            ' %s '
            'Check your credentials' % (len(names), str(names)))

注意在 boto.auth_handler 中定义的类 AuthHandler 的引用.

所以,可以看出我们需要查看boto.plugin.get_plugin(AuthHandler, requested_capability)的内容:

def get_plugin(cls, requested_capability=None):
    if not requested_capability:
        requested_capability = []
    result = []
    for handler in cls.__subclasses__():
        if handler.is_capable(requested_capability):
            result.append(handler)
    return result

所以,当我们看到 gcs_oauth2_boto_plugin.oauth2_plugin 中的类 OAuth2Auth 的类定义时,它终于变得清晰了。 ,其中它被声明为 boto.auth_handler.AuthHandler 的子类,通过以下成员变量向 boto 框架发送其身份验证功能:

capability = ['google-oauth2', 's3']

2- more generally, to be sure to understand the authentification process, if I want to run my app on a machine, I must be sure to have the .boto file (which points to my service account private key) generated previously? Or is there a cleaner/easier way to give access to my application to Google Storage for in/out interactions?

这有一个更通用的答案:您可以使用 .boto 文件,尽管您也可以使用服务帐户凭据,您甚至可以使用 REST API 并通过 oauth2 流程获取发送所需的 token 授权 header 。云存储授权的各种方法在文档中。您链接的教程/文档显示了一些方法,您已将 .boto 用于另一种方法。您可以阅读有关云存储 REST API (JSON) 的信息 here您可以阅读有关各种 python oauth2 流程的信息 here .

关于python - 使用 Python 对 Google Storage 进行身份验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33492567/

相关文章:

python - Azure SQL Server 批量插入 TCP 提供程序问题

python - 如何在 Python scikit-learn 中输出随机森林中每棵树的回归预测?

c# - Google Calendar API v3 - 在服务器上部署时请求超时

google-cloud-platform - 传输服务数据不一致: Google Ads (AdWords) <> BigQuery

javascript - Google Storage 签名 URL 过期导致 400 错误,没有 CORS header

c# - 在 C# 中将一个 int 数组拆分为多个 int 数组的列表

从完整文件路径中提取文件名及其父目录的Pythonic方法?

c# - 找不到类型或命名空间名称 'IAuthorizationState'

javascript - ngCordova:oauth 与谷歌失败

python - 如何从 Google App Engine 上的 URL 将文件存储在 Google Storage 上?