有的时候,当进行grpc调用的时候,并不希望客户端与服务端建立连接后直接就进入对应的方法体内。比如需要验证签名来确认客户端的身份,再执行相应的方法。这个时候就可以哟拿到Interceptor。
golang grpc的拦截器(Interceptor)为UnaryServerInterceptor,为一个指向函数的指针。
UnaryServerInterceptor在服务端对于一次RPC调用进行拦截。UnaryServerInterceptor是一个函数指针,当客户端进行grpc调用的时候,首先并不执行用户调用的方法,先执行UnaryServerInterceptor所指的函数,随后再进入真正要执行的函数。
grpc的UnaryServerInterceptor定义如下:
// UnaryServerInterceptor provides a hook to intercept the execution of a unary RPC on the server. info
// contains all the information of this RPC the interceptor can operate on. And handler is the wrapper
// of the service method implementation. It is the responsibility of the interceptor to invoke handler
// to complete the RPC.
type UnaryServerInterceptor func(ctx context.Context, req interface{}, info *UnaryServerInfo, handler UnaryHandler) (resp interface{}, err error)
req就是用户的请求参数,info中包含了此次调用的信息,handler就是客户端此次实际要调用的函数。
UnaryServerInfo的定义如下:
// UnaryServerInfo consists of various information about a unary RPC on
// server side. All per-rpc information may be mutated by the interceptor.
type UnaryServerInfo struct {
// Server is the service implementation the user provides. This is read-only.
Server interface{}
// FullMethod is the full RPC method string, i.e., /package.service/method.
FullMethod string
}
主要包含两个部分,Server成员,是客户编写的服务器端的服务实现,这个成员是只读的,FullMethod成员是要调用的方法名,这个方法名interceptor可以进行修改。所以说,如果需要进行服务端方法调用之前需要验签的话,interceptor可以这么写:
var interceptor grpc.UnaryServerInterceptor
interceptor = func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) {
//对req中的签名进行验证
//如果失败直接返回Nil,err=验证签名失败
//handler是客户端原来打算调用的方法,如果验证成功,执行真正的方法
return handler(ctx, req)
}
相应的服务端初始化程序就是类似这种写法:
lis, err := net.Listen("tcp", fmt.Sprintf(":%s", port))
if err != nil {
panic(err)
return
}
var opts []grpc.ServerOption//grpc为使用的第三方的grpc包
opts = append(opts, grpc.UnaryInterceptor(interceptor))
server := grpc.NewServer(opts...)
chatprt.RegisterChatServer()//填入相关参数
server.Serve(lis)
原文地址:https://www.cnblogs.com/ExMan/p/12269786.html