2019独角兽企业重金招聘Python工程师标准>>>

Interceptor

grpc服务端提供了interceptor功能,可以在服务端接收到请求时优先对请求中的数据做一些处理后再转交给指定的服务处理并响应,功能类似middleware,很适合在这里处理验证、日志等流程。

在自定义Token认证的示例中,认证信息是由每个服务中的方法处理并认证的,如果有大量的接口方法,这种姿势就太蛋疼了,每个接口实现都要先处理认证信息。这个时候interceptor就站出来解决了这个问题,可以在请求被转到具体接口之前处理认证信息,一处认证,到处无忧,看代码吧,修改hello-token项目的服务端实现:

server/main.go

package mainimport ("net"pb "github.com/Jergoo/go-grpc-example/proto""golang.org/x/net/context""google.golang.org/grpc""google.golang.org/grpc/codes"       // grpc 响应状态码"google.golang.org/grpc/credentials" // grpc认证包"google.golang.org/grpc/grpclog""google.golang.org/grpc/metadata" // grpc metadata包
)const (// Address gRPC服务地址Address = "127.0.0.1:50052"
)// 定义helloService并实现约定的接口
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 验证Token
func auth(ctx context.Context) error {md, ok := metadata.FromContext(ctx)if !ok {return grpc.Errorf(codes.Unauthenticated, "无Token认证信息")}var (appid  stringappkey 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认证信息无效: 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认证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))// 注册interceptorvar interceptor grpc.UnaryServerInterceptorinterceptor = func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) {err = auth(ctx)if err != nil {return}// 继续处理请求return handler(ctx, req)}opts = append(opts, grpc.UnaryInterceptor(interceptor))// 实例化grpc Servers := grpc.NewServer(opts...)// 注册HelloServicepb.RegisterHelloServer(s, HelloService)grpclog.Println("Listen on " + Address + " with TLS + Token + Interceptor")s.Serve(listen)
}

运行:

go run main.goListen on 50052 with TLS + Token

client/main.go

package mainimport (pb "github.com/Jergoo/go-grpc-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"// OpenTLS 是否开启TLS认证OpenTLS = true
)// customCredential 自定义认证
type customCredential struct{}func (c customCredential) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) {return map[string]string{"appid":  "101010","appkey": "i am key",}, nil
}func (c customCredential) RequireTransportSecurity() bool {if OpenTLS {return true}return false
}func main() {var err errorvar opts []grpc.DialOptionif OpenTLS {// TLS连接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())}// 指定自定义认证opts = append(opts, grpc.WithPerRPCCredentials(new(customCredential)))conn, err := grpc.Dial(Address, opts...)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)
}

运行客户端程序 client/main.go:

go run main.go// 认证成功结果
Hello gRPC
Token info: appid=101010,appkey=i am key// 认证失败结果:
rpc error: code = 16 desc = Token认证信息无效: appID=101010, appKey=i am not key

运行结果和hello-token项目一样,简单不,只需要在实例化server前注册需要的interceptor,就可以轻松解决那个蛋疼的问题,想注册几个就注册几个。

项目推荐:

go-grpc-middleware

这个项目对interceptor进行了封装,支持多个拦截器的链式组装,对于需要多种处理的地方使用起来会更方便些。

参考

本系列示例代码

  • go-grpc-example

转载于:https://my.oschina.net/ifraincoat/blog/879547

Golang gRPC实践 连载五 拦截器 Interceptor相关推荐

  1. gRPC学习记录(五)--拦截器分析

    对于此类调用拦截器是必不可少的,本篇就分析下拦截器的实现.(博主本来想分析源码的,但是水平不足,并发知识欠缺,看的不是很懂,哎,仍需努力),另外貌似不同版本有些差异,这里使用的是1.0.3版本. 1. ...

  2. Golang gRPC实践 连载六 内置Trace

    2019独角兽企业重金招聘Python工程师标准>>> 内置Trace grpc默认提供了客户端和服务端的trace日志,可惜没有提供自定义接口,当前只能查看基本的事件日志和请求日志 ...

  3. Golang gRPC实践 连载七 HTTP协议转换

    gRPC HTTP协议转换 正当有这个需求的时候,就看到了这个实现姿势.源自coreos的一篇博客,转载到了grpc官方博客gRPC with REST and Open APIs. etcd3改用g ...

  4. 用 Java 实现拦截器 Interceptor 的拦截功能

    Java 里的拦截器是动态拦截 action 调用的对象,它提供了一种机制可以使开发者可以定义在一个 action 执行的前后执行的代码,也可以在一个 action 执行前阻止其执行,同时也提供了一种 ...

  5. Flume-NG源码阅读之SourceRunner,及选择器selector和拦截器interceptor的执行

    在AbstractConfigurationProvider类中loadSources方法会将所有的source进行封装成SourceRunner放到了Map<String, SourceRun ...

  6. Resultful API的拦截(拦截器——Interceptor)

    目录 一.Resultful API的拦截三种方式 二.拦截器(Interceptor)的演示示例(springboot项目) 三.Interceptor拦截器特点 四.Filter过滤器.Inter ...

  7. OKHttp拦截器(Interceptor)

    一.拦截器一般作用 <1> URL重定向. <2> 请求体数据加密. <3> HEAD动态添加. <4> 请求日志抓取. 二.基础讲解 <1> ...

  8. Day75.Ajax、拦截器Interceptor、异常映射、自动|手动类型转换、类型校验

    目录 一.Ajax ★ 1. 基本类型参数传递  @ResponseBody响应体 2. Ajax传递实体类 3.Ajax传递实体类带级联属性 (非json 普通参数) @DateTimeFormat ...

  9. Struts2拦截器(Interceptor)原理详解

    1.    理解拦截器 1.1.    什么是拦截器: 拦截器,在AOP(Aspect-Oriented Programming)中用于在某个方法或字段被访问之前,进行拦截然后在之前或之后加入某些操作 ...

  10. struts2学习笔记--拦截器(Interceptor)和登录权限验证Demo

    理解 Interceptor拦截器类似于我们学过的过滤器,是可以在action执行前后执行的代码.是我们做web开发是经常使用的技术,比如权限控制,日志.我们也可以把多个interceptor连在一起 ...

最新文章

  1. Oracle 之 配置HugePages内存
  2. Visual Studio 2005 2008 2010样式
  3. python基本使用-python基本用法笔记合集
  4. c++和python先学哪个?
  5. options模块介绍
  6. docker重启后容器消失_docker设置固定ip地址
  7. 10 亿产业基金加持,让精准定位在物联网应用中实现无限可能!
  8. 贵阳清镇计算机培训,贵阳清镇电工培训中心
  9. speedoffice(PPT)怎么将背景设置为渐变的背景
  10. mysql数据库的简单查询一般是查询什么,MySQL的简单查询语句(十五)
  11. 运维分级发布_故障分级和处罚规范-运维必备规章制度
  12. 干货 | 6大商品数据分析模型分享!
  13. Android studio设计app登录界面
  14. webpack前端应用之基础打包
  15. 智能网联先导区道路交叉口车路协同系统设计
  16. 创建银行账户,实现存款,取款,转账(正解)
  17. java argox_HTML+CSS3再加一点点JS做的一个小时钟
  18. 云南省谷歌地球高程DEM等高线下载
  19. mysql 数据库信息泄露
  20. Latex:跨页多图

热门文章

  1. 2020-10-01
  2. 为啥mysql的load这么快_【MySQL】浅谈MySQL的LOAD DATA
  3. c++ 跳转到上级目录_基于VSCode和CMake进行C/C++开发第五讲IDEVSCode
  4. merge()函数--R语言
  5. 量子计算云平台“中国版”启动 量子信息革命正在加速到来
  6. “互联网+”时代,网络安全市场将达千亿级别
  7. 查看最大的10个文件
  8. Convirt 2.0 更新到 2.1版本
  9. 利用CentOS的yum更新源来实现RHEL5的YUM功能
  10. CLI里面的秘密……(二)强命名、元数据以及文件结构(上半部分)