http://doc.oschina.net/grpc?t=58010
認證
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 。
例子
通過 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 進行授權 (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())); ...