文章来自gRPC 官方文档中文版

认证

gRPC 被设计成可以利用插件的形式支持多种授权机制。本文档对多种支持的授权机制提供了一个概览,并且用例子来论述对应API,最后就其扩展性作了讨论。 马上将会推出更多文档和例子。

支持的授权机制

SSL/TLS

gRP 集成 SSL/TLS 并对服务端授权所使用的 SSL/TLS 进行了改良,对客户端和服务端交换的所有数据进行了加密。对客户端来讲提供了可选的机制提供凭证来获得共同的授权。

OAuth 2.0

gRPC 提供通用的机制(后续进行描述)来对请求和应答附加基于元数据的凭证。当通过 gRPC 访问 Google API 时,会为一定的授权流程提供额外的获取访问令牌的支持,这将通过以下代码例子进行展示。 警告:Google OAuth2 凭证应该仅用于连接 Google 的服务。把 Google 对应的 OAuth2 令牌发往非 Google 的服务会导致令牌被窃取用作冒充客户端来访问 Google 的服务。

API

为了减少复杂性和将混乱最小化, gRPC 以一个统一的凭证对象来进行工作。 凭证可以是以下两类:

  • 频道凭证, 被附加在 频道上, 比如 SSL 凭证。
  • 调用凭证, 被附加在调用上(或者 C++ 里的 客户端上下文)。 凭证可以用组合频道凭证来进行组合。一个组合频道凭证可以将一个频道凭证和一个调用凭证关联创建一个新的频道凭证。结果在这个频道上的每次调用会发送组合的调用凭证来作为授权数据。 例如,一各频道凭证可以由一个Ssl 凭证和一个访问令牌凭证生成。结果是在这个频道上的每次调用都会发送对应的访问令牌。 调用凭证可以用 组合凭证来组装。组装后的 调用凭证应用到一个客户端上下文里,将触发发送这两个调用凭证的授权数据。

服务端认证加密使用的 SSL/TLS

这是个最简单的认证场景:一个客户端仅仅想认证服务器并且加密所有数据。

  1. // Create a default SSL ChannelCredentials object.
  2. auto channel_creds = grpc::SslCredentials(grpc::SslCredentialsOptions());
  3. // Create a channel using the credentials created in the previous step.
  4. auto channel = grpc::CreateChannel(server_name, creds);
  5. // Create a stub on the channel.
  6. std::unique_ptr<Greeter::Stub> stub(Greeter::NewStub(channel));
  7. // Make actual RPC calls on the stub.
  8. grpc::Status s = stub->sayHello(&context, *request, response);

对于高级的用例比如改变根 CA 或使用客户端证书,可以在发送给工厂方法的 SslCredentialsOptions 参数里的相应选项进行设置。

通过 Google 进行认证

gRPC应用可以使用一个简单的API来创建一个可以工作在不同部署场景下的凭证。

  1. auto creds = grpc::GoogleDefaultCredentials();
  2. // Create a channel, stub and make RPC calls (same as in the previous example)
  3. auto channel = grpc::CreateChannel(server_name, creds);
  4. std::unique_ptr<Greeter::Stub> stub(Greeter::NewStub(channel));
  5. grpc::Status s = stub->sayHello(&context, *request, response);

这个应用使用的频道凭证对象就像 Google 计算引擎 (GCE)里运行的应用一样使用服务账号。在前面的案例里,服务账号的密钥从环境变量 GOOGLE_APPLICATION_CREDENTIALS 对应的文件里加载。这些密钥被用来生成承载令牌附加在在相应频道的每次 RPC 调用里。 对于 GCE 里运行的应用,可以在虚拟机设置的时候为其配置一个默认的服务账号和相应的 OAuth2 范围。在运行时,这个凭证被用来与认证系统通讯来获取 OAuth2 访问令牌并且把令牌用作在相应的频道上的 RPC 调用。

扩展 gRPC 支持其他的认证机制

相应的凭证插件 API 允许开发者开发自己的凭证插件。

  • MetadataCredentialsPlugin 抽象类包含需要被开发者创建的子类实现的纯虚方法 GetMetadata
  • MetadataCredentialsFromPlugin 方法可以从 MetadataCredentialsPlugin 创建一个 调用者凭证。 这类有个简单的凭证插件例子,是通过在自定义头了设置一个认证票据。
  1. class MyCustomAuthenticator : public grpc::MetadataCredentialsPlugin {
  2. public:
  3. MyCustomAuthenticator(const grpc::string& ticket) : ticket_(ticket) {}
  4. grpc::Status GetMetadata(
  5. grpc::string_ref service_url, grpc::string_ref method_name,
  6. const grpc::AuthContext& channel_auth_context,
  7. std::multimap<grpc::string, grpc::string>* metadata) override {
  8. metadata->insert(std::make_pair("x-custom-auth-ticket", ticket_));
  9. return grpc::Status::OK;
  10. }
  11. private:
  12. grpc::string ticket_;
  13. };
  14. auto call_creds = grpc::MetadataCredentialsFromPlugin(
  15. std::unique_ptr<grpc::MetadataCredentialsPlugin>(
  16. new MyCustomAuthenticator("super-secret-ticket")));

更深层次的集成可以通过在将 gRPC 的凭证实现以插件的形式集成进核心层。gRPC 内部也允许用其他加密机制来替换 SSL/TLS 。

例子

这些授权机制将会在所有 gRPC 支持的语言里提供。以下的一些节里展示了上文提到的认证和授权在每种语言里如何实现:很快将会推出更多语言的支持。

通过 SSL/TLS 进行服务端授权和加密(Ruby)

  1. # Base case - No encryption
  2. stub = Helloworld::Greeter::Stub.new('localhost:50051', :this_channel_is_insecure)
  3. ...
  4. # With server authentication SSL/TLS
  5. creds = GRPC::Core::Credentials.new(load_certs) # load_certs typically loads a CA roots file
  6. stub = Helloworld::Greeter::Stub.new('localhost:50051', creds)

通过 SSL/TLS 进行服务端授权和加密 (C#)

  1. // Base case - No encryption/authentication
  2. var channel = new Channel("localhost:50051", ChannelCredentials.Insecure);
  3. var client = new Greeter.GreeterClient(channel);
  4. ...
  5. // With server authentication SSL/TLS
  6. var channelCredentials = new SslCredentials(File.ReadAllText("roots.pem")); // Load a custom roots file.
  7. var channel = new Channel("myservice.example.com", channelCredentials);
  8. var client = new Greeter.GreeterClient(channel);

通过 SSL/TLS 进行服务端授权和加密 (Python)

  1. from grpc.beta import implementations
  2. import helloworld_pb2
  3. # Base case - No encryption
  4. channel = implementations.insecure_channel('localhost', 50051)
  5. stub = helloworld_pb2.beta_create_Greeter_stub(channel)
  6. ...
  7. # With server authentication SSL/TLS
  8. creds = implementations.ssl_channel_credentials(open('roots.pem').read(), None, None)
  9. channel = implementations.secure_channel('localhost', 50051, creds)
  10. stub = helloworld_pb2.beta_create_Greeter_stub(channel)

通过 Google 进行授权 (Ruby)

基本案例 - 无加密/授权

  1. stub = Helloworld::Greeter::Stub.new('localhost:50051', :this_channel_is_insecure)

用无限制凭证进行授权 (推荐途径)

  1. require 'googleauth' # from http://www.rubydoc.info/gems/googleauth/0.1.0
  2. ...
  3. ssl_creds = GRPC::Core::ChannelCredentials.new(load_certs) # load_certs typically loads a CA roots file
  4. authentication = Google::Auth.get_application_default()
  5. call_creds = GRPC::Core::CallCredentials.new(authentication.updater_proc)
  6. combined_creds = ssl_creds.compose(call_creds)
  7. stub = Helloworld::Greeter::Stub.new('greeter.googleapis.com', combined_creds)

用 OAuth2 令牌进行认证(传统途径)

  1. require 'googleauth' # from http://www.rubydoc.info/gems/googleauth/0.1.0
  2. ...
  3. ssl_creds = GRPC::Core::ChannelCredentials.new(load_certs) # load_certs typically loads a CA roots file
  4. scope = 'https://www.googleapis.com/auth/grpc-testing'
  5. authentication = Google::Auth.get_application_default(scope)
  6. call_creds = GRPC::Core::CallCredentials.new(authentication.updater_proc)
  7. combined_creds = ssl_creds.compose(call_creds)
  8. stub = Helloworld::Greeter::Stub.new('greeter.googleapis.com', combined_creds)

通过 Google 进行授权 (Node.js)

基本案例 - 无加密/授权

  1. var stub = new helloworld.Greeter('localhost:50051', grpc.credentials.createInsecure());

用无限制凭证进行授权 (推荐途径)

  1. // Authenticating with Google
  2. var GoogleAuth = require('google-auth-library'); // from https://www.npmjs.com/package/google-auth-library
  3. ...
  4. var ssl_creds = grpc.credentials.createSsl(root_certs);
  5. (new GoogleAuth()).getApplicationDefault(function(err, auth) {
  6. var call_creds = grpc.credentials.createFromGoogleCredential(auth);
  7. var combined_creds = grpc.credentials.combineChannelCredentials(ssl_creds, call_creds);
  8. var stub = new helloworld.Greeter('greeter.googleapis.com', combined_credentials);
  9. });

用 OAuth2 令牌进行认证(传统途径)

  1. var GoogleAuth = require('google-auth-library'); // from https://www.npmjs.com/package/google-auth-library
  2. ...
  3. var ssl_creds = grpc.Credentials.createSsl(root_certs); // load_certs typically loads a CA roots file
  4. var scope = 'https://www.googleapis.com/auth/grpc-testing';
  5. (new GoogleAuth()).getApplicationDefault(function(err, auth) {
  6. if (auth.createScopeRequired()) {
  7. auth = auth.createScoped(scope);
  8. }
  9. var call_creds = grpc.credentials.createFromGoogleCredential(auth);
  10. var combined_creds = grpc.credentials.combineChannelCredentials(ssl_creds, call_creds);
  11. var stub = new helloworld.Greeter('greeter.googleapis.com', combined_credentials);
  12. });

通过 Google 进行授权 (C#)

基本案例 - 无加密/授权

  1. var channel = new Channel("localhost:50051", ChannelCredentials.Insecure);
  2. var client = new Greeter.GreeterClient(channel);
  3. ...

用无限制凭证进行授权 (推荐途径)

  1. using Grpc.Auth; // from Grpc.Auth NuGet package
  2. ...
  3. // Loads Google Application Default Credentials with publicly trusted roots.
  4. var channelCredentials = await GoogleGrpcCredentials.GetApplicationDefaultAsync();
  5. var channel = new Channel("greeter.googleapis.com", channelCredentials);
  6. var client = new Greeter.GreeterClient(channel);
  7. ...

用 OAuth2 令牌进行认证(传统途径)

  1. using Grpc.Auth; // from Grpc.Auth NuGet package
  2. ...
  3. string scope = "https://www.googleapis.com/auth/grpc-testing";
  4. var googleCredential = await GoogleCredential.GetApplicationDefaultAsync();
  5. if (googleCredential.IsCreateScopedRequired)
  6. {
  7. googleCredential = googleCredential.CreateScoped(new[] { scope });
  8. }
  9. var channel = new Channel("greeter.googleapis.com", googleCredential.ToChannelCredentials());
  10. var client = new Greeter.GreeterClient(channel);
  11. ...

授权一个 gRPC 调用

  1. var channel = new Channel("greeter.googleapis.com", new SslCredentials()); // Use publicly trusted roots.
  2. var client = new Greeter.GreeterClient(channel);
  3. ...
  4. var googleCredential = await GoogleCredential.GetApplicationDefaultAsync();
  5. var result = client.SayHello(request, new CallOptions(credentials: googleCredential.ToCallCredentials()));
  6. ...

通过 Google 进行授权 (PHP)

基本案例 - 无加密/授权

  1. $client = new helloworld\GreeterClient('localhost:50051', [
  2. 'credentials' => Grpc\ChannelCredentials::createInsecure(),
  3. ]);
  4. ...

用无限制凭证进行授权 (推荐途径)

Authenticate using scopeless credentials (recommended approach)

  1. function updateAuthMetadataCallback($context)
  2. {
  3. $auth_credentials = ApplicationDefaultCredentials::getCredentials();
  4. return $auth_credentials->updateMetadata($metadata = [], $context->service_url);
  5. }
  6. $channel_credentials = Grpc\ChannelCredentials::createComposite(
  7. Grpc\ChannelCredentials::createSsl(file_get_contents('roots.pem')),
  8. Grpc\CallCredentials::createFromPlugin('updateAuthMetadataCallback')
  9. );
  10. $opts = [
  11. 'credentials' => $channel_credentials
  12. ];
  13. $client = new helloworld\GreeterClient('greeter.googleapis.com', $opts);
  14. `

用 OAuth2 令牌进行认证(传统途径)

  1. // the environment variable "GOOGLE_APPLICATION_CREDENTIALS" needs to be set
  2. $scope = "https://www.googleapis.com/auth/grpc-testing";
  3. $auth = Google\Auth\ApplicationDefaultCredentials::getCredentials($scope);
  4. $opts = [
  5. 'credentials' => Grpc\Credentials::createSsl(file_get_contents('roots.pem'));
  6. 'update_metadata' => $auth->getUpdateMetadataFunc(),
  7. ];
  8. $client = new helloworld\GreeterClient('greeter.googleapis.com', $opts);

通过 Google 进行授权 (Python)

基本案例 - 无加密/授权

  1. channel = implementations.insecure_channel('localhost', 50051)
  2. stub = helloworld_pb2.beta_create_Greeter_stub(channel)
  3. ...

用 OAuth2 令牌进行认证(传统途径)

  1. transport_creds = implementations.ssl_channel_credentials(open('roots.pem').read(), None, None)
  2. def oauth2token_credentials(context, callback):
  3. try:
  4. credentials = oauth2client.client.GoogleCredentials.get_application_default()
  5. scoped_credentials = credentials.create_scoped([scope])
  6. except Exception as error:
  7. callback([], error)
  8. return
  9. callback([('authorization', 'Bearer %s' % scoped_credentials.get_access_token().access_token)], None)
  10. auth_creds = implementations.metadata_plugin_credentials(oauth2token_credentials)
  11. channel_creds = implementations.composite_channel_credentials(transport_creds, auth_creds)
  12. channel = implementations.secure_channel('localhost', 50051, channel_creds)
  13. stub = helloworld_pb2.beta_create_Greeter_stub(channel)

gRPC官方文档(安全认证)的更多相关文章

  1. gRPC官方文档(gRPC基础:C++)

    文章来自gRPC 官方文档中文版 本教程提供了C++程序员如何使用gRPC的指南. 通过学习教程中例子,你可以学会如何: 在一个 .proto 文件内定义服务. 用 protocol buffer 编 ...

  2. gRPC官方文档(异步基础: C++)

    文章来自gRPC 官方文档中文版 异步基础: C++ 本教程介绍如何使用 C++ 的 gRPC 异步/非阻塞 API 去实现简单的服务器和客户端.假设你已经熟悉实现同步 gRPC 代码,如gRPC 基 ...

  3. gRPC官方文档(通讯协议)

    文章来自gRPC 官方文档中文版 HTTP2 协议上的 gRPC 本文档作为 gRPC 在 HTTP2 草案17框架上的实现的详细描述,假设你已经熟悉 HTTP2 的规范.产品规则采用的是ABNF 语 ...

  4. gRPC官方文档(概览)

    文章来自gRPC 官方文档中文版 概览 开始 欢迎进入 gRPC 的开发文档,gRPC 一开始由 google 开发,是一款语言中立.平台中立.开源的远程过程调用(RPC)系统. 本文档通过快速概述和 ...

  5. gRPC官方文档(概念)

    文章来自gRPC 官方文档中文版 gRPC 概念 本文档通过对于 gRPC 的架构和 RPC 生命周期的概览来介绍 gRPC 的主要概念.本文是在假设你已经读过文档部分的前提下展开的.针对具体语言细节 ...

  6. thinkphp5的auth权限认证(转自thinkphp官方文档+自己总结)

    thinkphp5的auth权限认证(转自thinkphp官方文档+自己总结) 一.总结 一句话总结:相当于就是用其它thinkphp的扩展一样,都是引入扩展,配置扩展,然后使用 引入 配置 使用 基 ...

  7. Hui之Hui.js 官方文档

    基础 // 判断值是否是指定数据类型 var result = hui.isTargetType("百签软件", "string"); //=>true ...

  8. CentOS7.3利用kubeadm安装kubernetes1.7.3完整版(官方文档填坑篇)

    安装前记: 近来容器对企业来说已经不是什么陌生的概念,Kubernetes作为Google开源的容器运行平台,受到了大家的热捧.搭建一套完整的kubernetes平台,也成为试用这套平台必须迈过的坎儿 ...

  9. Spring Cloud官方文档中文版-Spring Cloud Config(上)

    官方文档地址为:http://cloud.spring.io/spring-cloud-static/Dalston.SR2/#spring-cloud-feign 文中例子我做了一些测试在:http ...

随机推荐

  1. 1.react的基础知识

    React 的基础之:JSX 语法 react 使用 JSX 语法,js 代码中可以写 HTML 代码. let myTitle = <h1>Hello, World!</h1> ...

  2. compile cef2526

    fetch --nohooks chromium cd /path/to/chromium/src# git checkout -b 51.0.2704.103 refs/tags/51.0.2704 ...

  3. BMP格式转JPEG格式

    int Bmp2Jpg(const char *bmp_data, const char *jeg_file, const int width, const int height) { int ret ...

  4. 使用PHP的GD2裁剪 + 缩放图片

    /** * 裁剪 + 缩放图片 * @param array $params 包含x,y,width,height,path * @return string */ public function t ...

  5. AD的差分输入与单端输入

    AD的差分输入与单端输入 单端输入,输入信号均以共同的地线为基准.这种输入方法主要应用于输入信号电压较高(高于1V),信号源到模拟输入硬件的导线较短(低于15 ft,1ft=304.8mm),且所有的 ...

  6. java代码流类。。程序怎么跟书上的结果不一样???

    总结:这个程序很容易懂.的那是这个结果我觉得有问题啊..怎么“stop”后,输出的内容是输入过的呢? 应该是没有关系的呀,与输入的值是不同的....怎么书上运行的结果和我的不一样啊 package c ...

  7. 阿里巴巴开源项目: canal 基于mysql数据库binlog的增量订阅&消费

    背景 早期,阿里巴巴B2B公司因为存在杭州和美国双机房部署,存在跨机房同步的业务需求.不过早期的数据库同步业务,主要是基于trigger的方式获取增 量变更,不过从2010年开始,阿里系公司开始逐步的 ...

  8. Shell脚本把文件从GBK转为UTF-8编码

    http://www.jb51.net/article/51308.htm 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 ...

  9. python的raw_input()函数。 函数的可变对象和不可变对象作为参数传递。

    python的raw_input()函数, 接受键盘输入, 其返回值是字符串类型, 所以当输入的是数字时, 如果是想参与算术运算, 必须要对其进行类型转换. python的参数传递, 对于可变对象和不 ...

  10. java selenium webdriver第二讲 页面元素定位

    自动化测试实施过程中,测试程序中常用的页面操作有三个步骤 1.定位网页上的页面元素,并存储到一个变量中 2.对变量中存储的页面元素进行操作,单击,下拉或者输入文字等 3.设定页面元素的操作值,比如,选 ...