文章来自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

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

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

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

通过 Google 进行认证

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

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

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

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

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

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

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

例子

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

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

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

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

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

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

from grpc.beta import implementations
import helloworld_pb2 # Base case - No encryption
channel = implementations.insecure_channel('localhost', 50051)
stub = helloworld_pb2.beta_create_Greeter_stub(channel)
... # With server authentication SSL/TLS
creds = implementations.ssl_channel_credentials(open('roots.pem').read(), None, None)
channel = implementations.secure_channel('localhost', 50051, creds)
stub = helloworld_pb2.beta_create_Greeter_stub(channel)

通过 Google 进行授权 (Ruby)

基本案例 - 无加密/授权

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

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

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

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

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

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

基本案例 - 无加密/授权

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

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

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

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

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

通过 Google 进行授权 (C#)

基本案例 - 无加密/授权

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

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

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

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

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

授权一个 gRPC 调用

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

通过 Google 进行授权 (PHP)

基本案例 - 无加密/授权

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

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

Authenticate using scopeless credentials (recommended approach)

function updateAuthMetadataCallback($context)
{
$auth_credentials = ApplicationDefaultCredentials::getCredentials();
return $auth_credentials->updateMetadata($metadata = [], $context->service_url);
}
$channel_credentials = Grpc\ChannelCredentials::createComposite(
Grpc\ChannelCredentials::createSsl(file_get_contents('roots.pem')),
Grpc\CallCredentials::createFromPlugin('updateAuthMetadataCallback')
);
$opts = [
'credentials' => $channel_credentials
];
$client = new helloworld\GreeterClient('greeter.googleapis.com', $opts);
`

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

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

通过 Google 进行授权 (Python)

基本案例 - 无加密/授权

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

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

transport_creds = implementations.ssl_channel_credentials(open('roots.pem').read(), None, None)
def oauth2token_credentials(context, callback):
try:
credentials = oauth2client.client.GoogleCredentials.get_application_default()
scoped_credentials = credentials.create_scoped([scope])
except Exception as error:
callback([], error)
return
callback([('authorization', 'Bearer %s' % scoped_credentials.get_access_token().access_token)], None) auth_creds = implementations.metadata_plugin_credentials(oauth2token_credentials)
channel_creds = implementations.composite_channel_credentials(transport_creds, auth_creds)
channel = implementations.secure_channel('localhost', 50051, channel_creds) 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. oracle如何查看表空间

    1.用户 查看当前用户的缺省表空间 SQL>select username,default_tablespace from user_users; 查看当前用户的角色 SQL>select ...

  2. 2015 浙江省赛 Beauty of Array (思维题)

    Beauty of Array Edward has an array A with N integers. He defines the beauty of an array as the summ ...

  3. qt安装必要的库 qt开源安装包下载

    yum install mesa-libGL-devel mesa-libGLU-devel #yum install freeglut-devel http://www.qt.io/download ...

  4. 如何深度优化MySQL内核

    MYSQL数据库适用场景广泛,相较于Oracle.DB2性价比更高,Web网站.日志系统.数据仓库等场景都有MYSQL用武之地,但是也存在对于事务性支持不太好(MySQL 5.5版本开始默认引擎才是I ...

  5. 微信开发准备(一)--Maven仓库管理新建WEB项目

    转自:http://www.cuiyongzhi.com/post/13.html 在我们的项目开发中经常会遇到项目周期很长,项目依赖jar包特别多的情况,所以我们经常会在项目中引入Maven插件,建 ...

  6. 重启Oracle服务

    转自:https://blog.csdn.net/wu2700222/article/details/78021207 #su– oracle sqlplus/ as sysdba //关闭服务 sh ...

  7. [Python Study Notes]七彩散点图绘制

    ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ...

  8. TabHost两种不同的实现方式

    第一种:继承TabActivity,从TabActivity中用getTabHost()方法获取TabHost.只要定义具体Tab内容布局就行了 第二种:不用继承TabActivity,在布局文件中定 ...

  9. bzoj 2653 middle(主席树)

    题面:https://vjudge.net/problem/HYSBZ-2653 博客:https://blog.csdn.net/litble/article/details/78984846 这个 ...

  10. ROS探索总结(四)——简单的机器人仿真

    前边我们已经介绍了ROS的基本情况,以及新手入门ROS的初级教程,现在就要真正的使用ROS进入机器人世界了.接下来我们涉及到的很多例程都是<ROS by Example>这本书的内容,我是 ...