【问题标题】:Python gRPC client request only with bearer token仅使用不记名令牌的 Python gRPC 客户端请求
【发布时间】:2020-05-11 10:45:31
【问题描述】:

我按照从here 生成 Python gPRC 客户端的说明进行操作,但很难为请求提供令牌

不安全的通道不起作用

auth_creds = grpc.access_token_call_credentials(TOKEN)
channel = grpc.insecure_channel('localhost:10000', auth_creds)

>> TypeError: 'CallCredentials' object is not iterable

安全通道也不起作用

auth_creds = grpc.access_token_call_credentials(TOKEN)
channel = grpc.secure_channel('localhost:10000', auth_creds)

>> TypeError: Argument 'channel_credentials' has incorrect type (expected grpc._cython.cygrpc.ChannelCredentials, got grpc._cython.cygrpc.MetadataPluginCallCredentials)

根据python gRPC documentation

CallCredentials 必须与安全通道一起使用,否则元数据将不会传输到服务器。

但是,我如何创建一个安全通道,因为创建这些 ChannelCredentials 的方法对应于 ssl 或类似的,不是吗?

除此之外,似乎可以简单地将元组{'Authorization':'Bearer <TOKEN>'} 解析为元数据,如here。但是,我注意到 - 正如在提出的评论中一样 - 不允许使用大写字符。

with_call 带有凭据的方法也不起作用

auth_creds = grpc.access_token_call_credentials(TOKEN)
channel = grpc.secure_channel('localhost:10000', auth_creds)
stub = foo_bar_pb2_grpc.ServiceStub(channel)
response = stub.Get.with_call(message_pb2.Message(), credentials=auth_creds)

>> TypeError: Argument 'channel_credentials' has incorrect type (expected grpc._cython.cygrpc.ChannelCredentials, got grpc._cython.cygrpc.MetadataPluginCallCredentials)

with_call 带有元数据的方法也不起作用

metadata = 'Authorization', 'Bearer <TOKEN>'
channel = grpc.insecure_channel('localhost:10000')
stub = foo_bar_pb2_grpc.ServiceStub(channel)
response = stub.Get.with_call(message_pb2.Message(), metadata=metadata))

>> ValueError: too many values to unpack (expected 2)

总结:如何使用访问令牌对客户端进行身份验证?

【问题讨论】:

    标签: python client grpc bearer-token


    【解决方案1】:

    如同一docstring所述:

    一个 CallCredentials 可以与 ChannelCredentials 组成以始终 为该 Channel 上的每个调用声明身份。

    ChannelCredentials 对象正是您来自grpc.secure_channel 的类型错误所尖叫的原因。 要进行该组合,您需要使用 SSL/TLS 加密通道。 这是一个带有令牌的客户端示例:

    with open("server.crt", 'rb') as fd:
        root_c = fd.read()
    scc = grpc.ssl_channel_credentials(root_certificates=root_c)
    
    tok = grpc.access_token_call_credentials("super-secret-token")
    ccc = grpc.composite_channel_credentials(scc, tok)
    
    with grpc.secure_channel("localhost:8080", ccc) as channel:
        #... create stub and do the call
        pass
    

    有关 SSL 结帐的更完整示例,请访问 https://github.com/joekottke/python-grpc-sslhttps://www.sandtable.com/using-ssl-with-grpc-in-python/official doc 也可能有助于查看。

    令牌是您不希望任何人嗅到的东西,我想这就是为什么 gRPC 库要求您在 secure_channel 中使用它的原因。

    【讨论】:

      【解决方案2】:

      我在尝试在安全通道中发送自定义标头时遇到了类似问题。

      就我而言,问题来自于使用:

      metadata = (('my-header-key', 'my-header-value'))
      

      代替:

      metadata = [('my-header-key', 'my-header-value')]
      

      我的代码:

      credentials = grpc.ssl_channel_credentials()
      with grpc.secure_channel("<HOST>:<PORT>", credentials) as channel:
          rpc_service = my_pb2_grpc.MyServiceStub(channel)
          request = my_pb2.MyData(my_data='data')
          metadata = [('my-header-key', 'my-header-value')]
          response = rpc_service.MyMethod(request=request, metadata=metadata)
      

      【讨论】:

        猜你喜欢
        • 2021-07-20
        • 2017-10-06
        • 1970-01-01
        • 2021-07-25
        • 2021-05-18
        • 1970-01-01
        • 1970-01-01
        • 2021-05-22
        • 1970-01-01
        相关资源
        最近更新 更多