This is a creation in Article, where the information may have evolved or changed.
The GRPC provides two authentication methods by default:
Two ways to mix it up
TLS Authentication Example
This directly expands the Hello project to implement the TLS authentication mechanism
First you need to prepare a certificate, in the Hello directory the new keys directory is used to store the certificate file.
Certificate making
Making the private key (. Key)
# Key considerations for algorithm "RSA" ≥ 2048-bitopenssl 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
Self-signed public key (X509) (pem-encodings .pem
| .crt
)
openssl req -new -x509 -sha256 -key server.key -out server.pem -days 3650
Custom Information
-----Country Name (2 letter code) [AU]:CNState or Province Name (full name) [Some-State]:XxXxLocality Name (eg, city) []:XxXxOrganization Name (eg, company) [Internet Widgits Pty Ltd]:XX Co. LtdOrganizational Unit Name (eg, section) []:DevCommon Name (e.g. server FQDN or YOUR name) []:server nameEmail Address []:xxx@xxx.com
Directory structure
$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编译后文件
Sample code
proto/helloworld.proto
and proto/hello.pb.go
documents need not be changed
Modify server-side code: SERVER/MAIN.GO
Package Mainimport ("net" PB "Go-grpc-practice/example/proto" "Golang.org/x/net/context" "google.golang.org/g RPC "Google.golang.org/grpc/credentials"//Introduction of GRPC Certification Package "Google.golang.org/grpc/grpclog") const (//Address GRPC Service Address = "127.0.0.1:50052")//define HelloService and implement the agreed interface 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 authentication creds, ERR: = credentials. Newservertlsfromfile (".. /.. /keys/server.pem ",". /.. /keys/server.key ") if err! = Nil {grpclog. Fatalf ("Failed to generate credentials%v", err)}//Instantiate Grpc Server and turn on TLS authentication s: = Grpc. NewServer (GRPC. Creds (creds))//Register HelloService Pb. Registerhelloserver (S, HelloService) Grpclog. Println ("Listen on" + Address + "with TLS") S.serve (Listen)}
Run:
go run main.goListen on 127.0.0.1:50052 with TLS
The service side can configure multiple options when instantiating GRPC server, one of which is TLS authentication
Client Add TLS authentication: Client/main.go
package mainimport ( 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)}
Run:
go run main.goHello gRPC
The client adds TLS authentication in a similar manner to the server, where you Dial
can configure multiple options when creating a connection, and more options are shown in the following example.
Token Authentication Example
Further, continue to expand the HELLO-TLS project to implement the TLS + token authentication mechanism
Directory structure
$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编译后文件
Sample code
Client implementation: Client/main.go
Package Mainimport (pb "Go-grpc-practice/example/proto"//introduced Proto Pack "Golang.org/x/net/context" "google.golang.or G/grpc "Google.golang.org/grpc/credentials"//Introduction of GRPC Authentication package "Google.golang.org/grpc/grpclog") const (//Address GRP C Service address = "127.0.0.1:50052"//Opentls whether to turn on TLS authentication OPENTLS = true)//customcredential Custom Authentication type Customcredent Ial Struct{}func (c customcredential) Getrequestmetadata (CTX context. Context, Uri, String) (map[string]string, error) {return map[string]string{"AppID": "101010", "Appke Y ":" 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 connection 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 ())}//Use custom Authentication opts = Append (opts, Grpc. Withperrpccredentials (New (customcredential))) conn, err: = Grpc. Dial (Address, opts ...) If err! = Nil {grpclog. Fatalln (ERR)} defer conn. Close ()//Initialize client c: = PB. Newhelloclient (conn)//Call method Reqbody: = new (Pb). hellorequest) Reqbody.name = "Grpc" r, Err: = C.sayhello (context. Background (), reqbody) if err! = Nil {grpclog. Fatalln (Err)} grpclog. Println (R.message)}
Here we define a customCredential
structure and implement two methods GetRequestMetadata
and RequireTransportSecurity
. This is the custom authentication method provided by GRPC, and each RPC call transmits authentication information. customCredential
is actually implementing the grpc/credential
interface within the package PerRPCCredentials
. Each invocation, token information is transmitted to the server via the requested metadata. The following is a detailed look at how the server gets the information in metadata.
To modify the SayHello method in Server/main.go:
Package Mainimport ("FMT" "Net" PB "Go-grpc-practice/example/proto" "Golang.org/x/net/context" "Google.gol Ang.org/grpc "" Google.golang.org/grpc/codes "" google.golang.org/grpc/credentials "//introduced GRPC certification package" google.golang.org /grpc/grpclog "Google.golang.org/grpc/metadata"//introduction of GRPC meta-package) const (//Address GRPC Service addresses = "127.0.0.1 : 50052 ")//define HelloService and implement the agreed interface type HelloService struct{}//helloservice ... var helloservice = Helloservice{}func (h HelloService) SayHello (CTX context. Context, in *PB. Hellorequest) (*PB. Helloreply, error) {//parse the information in Metada and verify MD, OK: = metadata. Fromcontext (CTX) if!ok {return nil, grpc. Errorf (codes. Unauthenticated, "No token authentication information")} 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 Authentication information Invalid: 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 authentication creds, ERR: = credentials. Newservertlsfromfile (".. /.. /keys/server.pem ",". /.. /keys/server.key ") if err! = Nil {grpclog. Fatalf ("Failed to generate credentials%v", err)}//Instantiate Grpc Server and turn on TLS authentication s: = Grpc. NewServer (GRPC. Creds (creds))//Registered HelloService PB. Registerhelloserver (S, HelloService) Grpclog. Println ("Listen on" + Address + "with TLS + Token") S.serve (Listen)}
Run:
go run main.goListen on 50052 with TLS + Token
Run the client program Client/main.go:
go run main.go// 认证成功结果Hello gRPCToken info: appid=101010,appkey=i am key// 认证失败结果:rpc error: code = 16 desc = Token认证信息无效: appID=101010, appKey=i am not key
Reference
Sample code for this series