扫码订阅《 Go语言微服务框架学习实践》或入驻星球,即可阅读文章!

GOLANG ROADMAP · 知识星球

阅读模式

  • 沉浸
  • 自动
  • 日常
首页
Go路线图
  • 👶 初级要求:负责一个模块

    • 📗 薪资·10-15k 技能梳理
  • 🧑 中高级要求:负责一个方向

    • 📘 薪资·15-25k 技能梳理
  • 🧔 资深要求:负责一个领域

    • 📒 薪资·25-40k 技能梳理
  • 🧙 专家要求:负责多个领域

    • 📕 薪资·40k以上 技能梳理
Go学院
  • Go小课
  • Go小考
  • Go宝典
Go资源
  • 推荐资源

    • 优质课程
    • 推荐图书
    • 开源项目
  • 资源下载

    • 视频资源
    • 文档资源
    • 帮找资源
Go求职
  • 求职刷题

    • 企业题库
    • 面试宝典
    • 求职面经
  • 求职服务

    • 内推互助
    • 求职助力
    • 内推公司
推广返佣
  • 返佣排行
  • 返佣规则
  • 推广学院
更多
  • 用户中心

    • 我的信息
    • 我的消息
    • 我的返佣
author-avatar

GOLANG ROADMAP


首页
Go路线图
  • 👶 初级要求:负责一个模块

    • 📗 薪资·10-15k 技能梳理
  • 🧑 中高级要求:负责一个方向

    • 📘 薪资·15-25k 技能梳理
  • 🧔 资深要求:负责一个领域

    • 📒 薪资·25-40k 技能梳理
  • 🧙 专家要求:负责多个领域

    • 📕 薪资·40k以上 技能梳理
Go学院
  • Go小课
  • Go小考
  • Go宝典
Go资源
  • 推荐资源

    • 优质课程
    • 推荐图书
    • 开源项目
  • 资源下载

    • 视频资源
    • 文档资源
    • 帮找资源
Go求职
  • 求职刷题

    • 企业题库
    • 面试宝典
    • 求职面经
  • 求职服务

    • 内推互助
    • 求职助力
    • 内推公司
推广返佣
  • 返佣排行
  • 返佣规则
  • 推广学院
更多
  • 用户中心

    • 我的信息
    • 我的消息
    • 我的返佣
  • 《Go语言微服务框架学习实践》

    • 课程介绍
  • RPC远程调用机制

  • gRPC微服务框架

    • 第1节:gRPC介绍和安装
    • 第2节:gRPC框架使用
    • 第3节:gRPC调用
    • 第4节:TLS验证和Token认证
    • 第5节:拦截器的使用
  • go-micro微服务框架

扫码订阅《 Go语言微服务框架学习实践》或入驻星球,即可阅读文章!

第5节:拦截器的使用


GOLANG ROADMAP

# 需求

在上节课程中,我们学习使用了gRPC框架中的两种认证方式:TLS验证和Token验证。

但是,在服务端的方法中,每个方法都要进行token的判断。程序效率太低,可以优化一下处理逻辑,在调用服务端的具体方法之前,先进行拦截,并进行token验证判断,这种方式称之为拦截器处理。

除了此处的token验证判断处理以外,还可以进行日志处理等。

# Interceptor

使用拦截器,首先需要注册。 在grpc中编程实现中,可以在NewSever时添加拦截器设置,grpc框架中可以通过UnaryInterceptor方法设置自定义的拦截器,并返回ServerOption。具体代码如下:

grpc.UnaryInterceptor()
1

UnaryInterceptor()接收一个UnaryServerInterceptor类型,继续查看源码定义,可以发现UnaryServerInterceptor是一个func,定义如下:

type UnaryServerInterceptor func(ctx context.Context, req interface{}, info *UnaryServerInfo, handler UnaryHandler) (resp interface{}, err error)
1

通过以上代码,如果开发者需要注册自定义拦截器,需要自定义实现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)
}
1
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)
1

# 拦截器注册

在服务端调用grpc.NewServer时进行拦截器的注册。详细如下:

server := grpc.NewServer(grpc.Creds(creds), grpc.UnaryInterceptor(TokenInterceptor))
1

# 项目运行

依次运行server.go程序和client.go程序,可以得到程序运行的正确结果。修改token携带值,可以验证token非法情况的拦截器效果。

  • 需求
  • Interceptor
  • 自定义UnaryServerInterceptor
  • 拦截器注册
  • 项目运行