This is a creation in Article, where the information may have evolved or changed.
Interceptor
The GRPC server provides a interceptor function that takes precedence over the data in the request when the server receives the request and then transfers it to the specified service processing and response, similar to the middleware, which is a good place to process validation, logging, and so on.
In the example of custom token authentication, the authentication information is processed and certified by the methods in each service, and if there is a large number of interface methods, this posture is too painful, and each interface implementation must first process the authentication information. This time interceptor stand out to solve this problem, can be transferred to the specific interface before the request processing authentication information, a certification, everywhere worry-free, look at the code bar, modify the service-side implementation of the Hello-token project:
Server/main.go
Package Mainimport ("net" PB "Git.vodjk.com/go-grpc/example/proto" "Golang.org/x/net/context" "Google.golang. Org/grpc "Google.golang.org/grpc/codes"//GRPC Response status Code "Google.golang.org/grpc/credentials"//GRPC Certification Package "goo Gle.golang.org/grpc/grpclog "Google.golang.org/grpc/metadata"//GRPC Metadata Package) const (//Address GRPC service addresses ADDR ESS = "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}//auth validation tokenfunc auth (ctx context. Context) Error {MD, OK: = metadata. Fromcontext (CTX) if!ok {return 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 GRPC. Errorf (codes. Unauthenticated, "Token authentication information Invalid: appid=%s, appkey=%s", AppID, Appkey)} return Nil}func main () {listen, err: = Net . Listen ("TCP", Address) if err! = Nil {grpclog. Fatalf ("Failed to listen:%v", err)} var opts []grpc. Serveroption//TLS authentication creds, ERR: = credentials. Newservertlsfromfile (".. /.. /keys/server.pem ",". /.. /keys/server.key ") if err! = Nil {grpclog. Fatalf ("Failed to generate credentials%v", err)} opts = Append (opts, Grpc. Creds (creds))//Register Interceptor Var interceptor grpc. Unaryserverinterceptor Interceptor = func (CTX context. Context, req interface{}, Info *grpc. Unaryserverinfo, Handler Grpc. Unaryhandler) (Resp interface{}, err error) {err = Auth (ctx) if err! = Nil {return} Continue processing request return handler (CTX, req)} opts = Append (opts, Grpc. Unaryinterceptor (Interceptor))//Instantiate Grpc Server s: = Grpc. NewServer (opts ...) Register HelloService PB. Registerhelloserver (S, HelloService) Grpclog. Println ("Listen on" + Address + "with TLS + Token + Interceptor") 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
Run the results and Hello-token project, simple No, just need to register the server before the interceptor, you can easily solve the problem of the egg pain, want to register a few to register a few.
Project Recommendation:
Go-grpc-middleware
This project encapsulates the interceptor and supports chained assembly of multiple interceptors, which is easier to use in places where multiple processing is required.
Reference
Sample code for this series