gRPC持ち込み:RPCメソッドのカスタム認証
原文アドレス:gRPCを持ち込む:RPC方法に対してカスタム認証項目アドレスを行う:https://github.com/EDDYCJY/go...
前言
前の章では、グローバル認証に使用できる2つの方法について説明しました. TLS証明書認証 CAに基づくTLS証明書認証 Unary and Stream interceptor
実際のニーズでは、一部のモジュールのRPCメソッドに対して特別な認証や検証を行うことがよくあります.今日はこの機能点について説明し、実現します
授業前の知識
各RPCメソッドのコンテキストに必要なセキュリティ認証情報を追加する役割を果たす、gRPCではPerRPCCredentialsがデフォルトで定義されています.これが本章の主役です.gRPCでは、カスタム認証用のインタフェースがデフォルトで提供されています.2つの方法があります. GetRequestMetadata:現在の認証要求に必要なメタデータを取得する RequireTransportSecurity:TLS認証に基づく安全な伝送が必要かどうか .
ディレクトリ構造
新しいsimple_token_server/server.goとsimple_token_client/client.go、ディレクトリ構造は以下の通りです.
gRPC
Client
Client側では、 struct Auth:GetRequestMetadata、RequireTransportSecurity grpc.WithPerRPCCredentials
Server
サーバ側では簡単ですが、実際には
検証#ケンショウ#
serverを再起動します.goとclient.goは、以下の結果を得た.
クライアントを変更goの値は、製造両者が一致せず、無効な結果が得られます.
いちいちめんどくさい
私はあなたがきっと一つ一つ聞くと信じています.面倒でしょう.この考えを持っているあなたは、
まとめ
この章では、RPCメソッドのカスタム認証について簡単に説明しますが、グローバルにしたい場合は、ブロックから手を出すことをお勧めします.
リファレンス
このシリーズのサンプルコード go-grpc-example
シリーズディレクトリ gRPC持ち込み:gRPC及び関連紹介 は、gRPC:gRPC Client and Server に持ち込む.は、gRPC:gRPC Streaming、Client and Server を導入します.はgRPC:TLS証明書認証 を持ち込む. gRPC持ち込み:CAベースTLS証明書認証 gRPC:Unary and Stream interceptor に持ち込むはgRPCを持ち込みます:あなたのサービスにHTTPインタフェース を同時に提供させます. gRPC持ち込み:RPCメソッドのカスタム認証 gRPC:gRPC Deadlines に持ち込む
前言
前の章では、グローバル認証に使用できる2つの方法について説明しました.
実際のニーズでは、一部のモジュールのRPCメソッドに対して特別な認証や検証を行うことがよくあります.今日はこの機能点について説明し、実現します
授業前の知識
type PerRPCCredentials interface {
GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error)
RequireTransportSecurity() bool
}
各RPCメソッドのコンテキストに必要なセキュリティ認証情報を追加する役割を果たす、gRPCではPerRPCCredentialsがデフォルトで定義されています.これが本章の主役です.gRPCでは、カスタム認証用のインタフェースがデフォルトで提供されています.2つの方法があります.
ディレクトリ構造
新しいsimple_token_server/server.goとsimple_token_client/client.go、ディレクトリ構造は以下の通りです.
go-grpc-example
├── client
│ ├── simple_client
│ ├── simple_http_client
│ ├── simple_token_client
│ └── stream_client
├── conf
├── pkg
├── proto
├── server
│ ├── simple_http_server
│ ├── simple_server
│ ├── simple_token_server
│ └── stream_server
└── vendor
gRPC
Client
package main
import (
"context"
"log"
"google.golang.org/grpc"
"github.com/EDDYCJY/go-grpc-example/pkg/gtls"
pb "github.com/EDDYCJY/go-grpc-example/proto"
)
const PORT = "9004"
type Auth struct {
AppKey string
AppSecret string
}
func (a *Auth) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) {
return map[string]string{"app_key": a.AppKey, "app_secret": a.AppSecret}, nil
}
func (a *Auth) RequireTransportSecurity() bool {
return true
}
func main() {
tlsClient := gtls.Client{
ServerName: "go-grpc-example",
CertFile: "../../conf/server/server.pem",
}
c, err := tlsClient.GetTLSCredentials()
if err != nil {
log.Fatalf("tlsClient.GetTLSCredentials err: %v", err)
}
auth := Auth{
AppKey: "eddycjy",
AppSecret: "20181005",
}
conn, err := grpc.Dial(":"+PORT, grpc.WithTransportCredentials(c), grpc.WithPerRPCCredentials(&auth))
...
}
Client側では、
type PerRPCCredentials interface
に必要な方法を重点的に実現し、2点に注目すればよい.Server
package main
import (
"context"
"log"
"net"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/metadata"
"google.golang.org/grpc/status"
"github.com/EDDYCJY/go-grpc-example/pkg/gtls"
pb "github.com/EDDYCJY/go-grpc-example/proto"
)
type SearchService struct {
auth *Auth
}
func (s *SearchService) Search(ctx context.Context, r *pb.SearchRequest) (*pb.SearchResponse, error) {
if err := s.auth.Check(ctx); err != nil {
return nil, err
}
return &pb.SearchResponse{Response: r.GetRequest() + " Token Server"}, nil
}
const PORT = "9004"
func main() {
...
}
type Auth struct {
appKey string
appSecret string
}
func (a *Auth) Check(ctx context.Context) error {
md, ok := metadata.FromIncomingContext(ctx)
if !ok {
return status.Errorf(codes.Unauthenticated, " Token ")
}
var (
appKey string
appSecret string
)
if value, ok := md["app_key"]; ok {
appKey = value[0]
}
if value, ok := md["app_secret"]; ok {
appSecret = value[0]
}
if appKey != a.GetAppKey() || appSecret != a.GetAppSecret() {
return status.Errorf(codes.Unauthenticated, " Token ")
}
return nil
}
func (a *Auth) GetAppKey() string {
return "eddycjy"
}
func (a *Auth) GetAppSecret() string {
return "20181005"
}
サーバ側では簡単ですが、実際には
metadata.FromIncomingContext
を呼び出してコンテキストからmetadataを取得し、異なるRPCメソッドで認証チェックを行います.検証#ケンショウ#
serverを再起動します.goとclient.goは、以下の結果を得た.
$ go run client.go
2018/10/05 20:59:58 resp: gRPC Token Server
クライアントを変更goの値は、製造両者が一致せず、無効な結果が得られます.
$ go run client.go
2018/10/05 21:00:05 client.Search err: rpc error: code = Unauthenticated desc = invalid token
exit status 1
いちいちめんどくさい
私はあなたがきっと一つ一つ聞くと信じています.面倒でしょう.この考えを持っているあなたは、
type PerRPCCredentials interface
を遮断器(interceptor)にしなければなりません.まとめ
この章では、RPCメソッドのカスタム認証について簡単に説明しますが、グローバルにしたい場合は、ブロックから手を出すことをお勧めします.
リファレンス
このシリーズのサンプルコード
シリーズディレクトリ