# 需求
在上节课程中,我们学习使用了gRPC框架中的两种认证方式:TLS验证和Token验证。
但是,在服务端的方法中,每个方法都要进行token的判断。程序效率太低,可以优化一下处理逻辑,在调用服务端的具体方法之前,先进行拦截,并进行token验证判断,这种方式称之为拦截器处理。
除了此处的token验证判断处理以外,还可以进行日志处理等。
# Interceptor
使用拦截器,首先需要注册。 在grpc中编程实现中,可以在NewSever时添加拦截器设置,grpc框架中可以通过UnaryInterceptor方法设置自定义的拦截器,并返回ServerOption。具体代码如下:
grpc.UnaryInterceptor()
UnaryInterceptor()接收一个UnaryServerInterceptor类型,继续查看源码定义,可以发现UnaryServerInterceptor是一个func,定义如下:
type UnaryServerInterceptor func(ctx context.Context, req interface{}, info *UnaryServerInfo, handler UnaryHandler) (resp interface{}, err error)
通过以上代码,如果开发者需要注册自定义拦截器,需要自定义实现UnaryServerInterceptor的定义。
# 自定义UnaryServerInterceptor
接下来就自定义实现func,符合UnaryServerInterceptor的标准,在该func的定义中实现对token的验证逻辑。自定义实现func如下:
func TokenInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) {
//通过metadata
md, exist := metadata.FromIncomingContext(ctx)
if !exist {
return nil, status.Errorf(codes.Unauthenticated, "无Token认证信息")
}
var appKey string
var appSecret string
if key, ok := md["appid"]; ok {
appKey = key[0]
}
if secret, ok := md["appkey"]; ok {
appSecret = secret[0]
}
if appKey != "hello" || appSecret != "20190812" {
return nil, status.Errorf(codes.Unauthenticated, "Token 不合法")
}
//通过token验证,继续处理请求
return handler(ctx, req)
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
在自定义的TokenInterceptor方法定义中,和之前在服务的方法调用的验证逻辑一致,从metadata中取出请求头中携带的token认证信息,并进行验证是否正确。如果token验证通过,则继续处理请求后续逻辑,后续继续处理可以由grpc.UnaryHandler进行处理。grpc.UnaryHandler同样是一个方法,其具体的实现就是开发者自定义实现的服务方法。grpc.UnaryHandler接口定义源码定义如下:
type UnaryHandler func(ctx context.Context, req interface{}) (interface{}, error)
# 拦截器注册
在服务端调用grpc.NewServer时进行拦截器的注册。详细如下:
server := grpc.NewServer(grpc.Creds(creds), grpc.UnaryInterceptor(TokenInterceptor))
# 项目运行
依次运行server.go程序和client.go程序,可以得到程序运行的正确结果。修改token携带值,可以验证token非法情况的拦截器效果。