Golang gRPC練習シリアル4つのgRPC認定

gRPCデフォルトでは、2つの認証方法を提供します。

  • SSL / TLS認証に基づきます

  • リモートコール認証

二つのモードが混合することができます

TLS認証の例

TLS認証機構を達成するために、ここで直接拡張プロジェクトハロー

最初の証明書を準備するためにすべての必要性の、ハローディレクトリに新しいキーディレクトリは、証明書ファイルを格納するために使用されます。

証明書など

秘密鍵を作る(.KEY)

# Key considerations for algorithm "RSA" ≥ 2048-bit
openssl genrsa -out server.key 2048
    
# Key considerations for algorithm "ECDSA" ≥ secp384r1 # List ECDSA the supported curves (openssl ecparam -list_curves) openssl ecparam -genkey -name secp384r1 -out server.key

自己署名の公開鍵(X509)(PEM-エンコーディング  .pem| .crt

openssl req -new -x509 -sha256 -key server.key -out server.pem -days 3650

カスタム情報

-----
Country Name (2 letter code) [AU]:CN State or Province Name (full name) [Some-State]:XxXx Locality Name (eg, city) []:XxXx Organization Name (eg, company) [Internet Widgits Pty Ltd]:XX Co. Ltd Organizational Unit Name (eg, section) []:Dev Common Name (e.g. server FQDN or YOUR name) []:server name Email Address []:xxx@xxx.com

ディレクトリ構造

$GOPATH/src/grpc-go-practice/

example/
|—— hello-tls/
    |—— client/
        |—— main.go   // 客户端
    |—— server/
        |—— main.go // 服务端 |—— keys/ // 证书目录 |—— server.key |—— server.pem |—— proto/ |—— hello.proto // proto描述文件 |—— hello.pb.go // proto编译后文件

サンプルコード

proto/helloworld.protoそして、proto/hello.pb.goファイルを変更する必要はありません。

サーバーのコードを変更:サーバー/ main.go

package main

import (
    "net"

    pb "go-grpc-practice/example/proto"

    "golang.org/x/net/context" "google.golang.org/grpc" "google.golang.org/grpc/credentials" // 引入grpc认证包 "google.golang.org/grpc/grpclog" ) const ( // Address gRPC服务地址 Address = "127.0.0.1:50052" ) // 定义helloService并实现约定的接口 type helloService struct{} // HelloService ... var HelloService = helloService{} func (h helloService) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) { resp := new(pb.HelloReply) resp.Message = "Hello " + in.Name + "." return resp, nil } func main() { listen, err := net.Listen("tcp", Address) if err != nil { grpclog.Fatalf("failed to listen: %v", err) } // TLS认证 creds, err := credentials.NewServerTLSFromFile("../../keys/server.pem", "../../keys/server.key") if err != nil { grpclog.Fatalf("Failed to generate credentials %v", err) } // 实例化grpc Server, 并开启TLS认证 s := grpc.NewServer(grpc.Creds(creds)) // 注册HelloService pb.RegisterHelloServer(s, HelloService) grpclog.Println("Listen on " + Address + " with TLS") s.Serve(listen) }

実行します。

go run main.go

Listen on 127.0.0.1:50052 with TLS

サーバがgrpcサーバーをインスタンス化されると、さまざまなオプションを設定することができ、TLS認証は、そのうちの一つであります

クライアント/ main.go:TLSクライアント認証を追加します

package main

import (
    pb "go-grpc-practice/example/proto" // 引入proto包

    "golang.org/x/net/context" "google.golang.org/grpc" "google.golang.org/grpc/credentials" // 引入grpc认证包 "google.golang.org/grpc/grpclog" ) const ( // Address gRPC服务地址 Address = "127.0.0.1:50052" ) func main() { // TLS连接 creds, err := credentials.NewClientTLSFromFile("../../keys/server.pem", "server name") if err != nil { grpclog.Fatalf("Failed to create TLS credentials %v", err) } conn, err := grpc.Dial(Address, grpc.WithTransportCredentials(creds)) if err != nil { grpclog.Fatalln(err) } defer conn.Close() // 初始化客户端 c := pb.NewHelloClient(conn) // 调用方法 reqBody := new(pb.HelloRequest) reqBody.Name = "gRPC" r, err := c.SayHello(context.Background(), reqBody) if err != nil { grpclog.Fatalln(err) } grpclog.Println(r.Message) }

実行します。

go run main.go

Hello gRPC

TLSクライアントとサーバの認証方法を追加すると、接続を作成することに似てDial、同じことは、さまざまなオプションを設定することができ、後の例では、より多くのオプションが表示されます。

トークン認証の例

さらに、TLS +トークン認証メカニズムを実現するためのhello-TLSのプロジェクトを拡大し続けるために

ディレクトリ構造

$GOPATH/src/grpc-go-practice/

example/
|—— hello-token/
    |—— client/
        |—— main.go   // 客户端
    |—— server/
        |—— main.go // 服务端 |—— keys/ // 证书目录 |—— server.key |—— server.pem |—— proto/ |—— hello.proto // proto描述文件 |—— hello.pb.go // proto编译后文件

サンプルコード

クライアントの実装:クライアント/ main.go

package main

import (
    pb "go-grpc-practice/example/proto" // 引入proto包

    "golang.org/x/net/context" "google.golang.org/grpc" "google.golang.org/grpc/credentials" // 引入grpc认证包 "google.golang.org/grpc/grpclog" ) const ( // Address gRPC服务地址 Address = "127.0.0.1:50052" // OpenTLS 是否开启TLS认证 OpenTLS = true ) // customCredential 自定义认证 type customCredential struct{} func (c customCredential) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) { return map[string]string{ "appid": "101010", "appkey": "i am key", }, nil } func (c customCredential) RequireTransportSecurity() bool { if OpenTLS { return true } return false } func main() { var err error var opts []grpc.DialOption if OpenTLS { // TLS连接 creds, err := credentials.NewClientTLSFromFile("../../keys/server.pem", "server name") if err != nil { grpclog.Fatalf("Failed to create TLS credentials %v", err) } opts = append(opts, grpc.WithTransportCredentials(creds)) } else { opts = append(opts, grpc.WithInsecure()) } // 使用自定义认证 opts = append(opts, grpc.WithPerRPCCredentials(new(customCredential))) conn, err := grpc.Dial(Address, opts...) if err != nil { grpclog.Fatalln(err) } defer conn.Close() // 初始化客户端 c := pb.NewHelloClient(conn) // 调用方法 reqBody := new(pb.HelloRequest) reqBody.Name = "gRPC" r, err := c.SayHello(context.Background(), reqBody) if err != nil { grpclog.Fatalln(err) } grpclog.Println(r.Message) }

ここでは、定義しcustomCredentialた構造をして2つのメソッドを実装GetRequestMetadataしてRequireTransportSecurityこれは、各RPCコールが認証情報を転送します、gRPCが提供するカスタム認証です。customCredential実際に達成grpc/credentialパケットにPerRPCCredentialsインターフェース。各呼び出しは、トークン情報は、サーバによるメタデータの送信要求です。メタデータの情報にどのようにサーバー側のアクセスに以下の特定の外観。

ののsayHelloサーバ/ main.goを変更する方法:

package main

import (
    "fmt"
    "net"

    pb "go-grpc-practice/example/proto" "golang.org/x/net/context" "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/credentials" // 引入grpc认证包 "google.golang.org/grpc/grpclog" "google.golang.org/grpc/metadata" // 引入grpc meta包 ) const ( // Address gRPC服务地址 Address = "127.0.0.1:50052" ) // 定义helloService并实现约定的接口 type helloService struct{} // HelloService ... var HelloService = helloService{} func (h helloService) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) { // 解析metada中的信息并验证 md, ok := metadata.FromContext(ctx) if !ok { return nil, grpc.Errorf(codes.Unauthenticated, "无Token认证信息") } var ( appid string appkey string ) if val, ok := md["appid"]; ok { appid = val[0] } if val, ok := md["appkey"]; ok { appkey = val[0] } if appid != "101010" || appkey != "i am key" { return nil, grpc.Errorf(codes.Unauthenticated, "Token认证信息无效: appid=%s, appkey=%s", appid, appkey) } resp := new(pb.HelloReply) resp.Message = fmt.Sprintf("Hello %s.\nToken info: appid=%s,appkey=%s", in.Name, appid, appkey) return resp, nil } func main() { listen, err := net.Listen("tcp", Address) if err != nil { grpclog.Fatalf("failed to listen: %v", err) } // TLS认证 creds, err := credentials.NewServerTLSFromFile("../../keys/server.pem", "../../keys/server.key") if err != nil { grpclog.Fatalf("Failed to generate credentials %v", err) } // 实例化grpc Server, 并开启TLS认证 s := grpc.NewServer(grpc.Creds(creds)) // 注册HelloService pb.RegisterHelloServer(s, HelloService) grpclog.Println("Listen on " + Address + " with TLS + Token") s.Serve(listen) } 

実行します。

go run main.go

Listen on 50052 with TLS + Token

クライアントプログラムクライアント/ main.goを実行します。

go run main.go

// 认证成功结果
Hello gRPC
Token info: appid=101010,appkey=i am key // 认证失败结果: rpc error: code = 16 desc = Token认证信息无效: appID=101010, appKey=i am not key

参照

サンプルコードこの一連の

おすすめ

転載: www.cnblogs.com/ExMan/p/12163111.html