专栏首页GoLang那点事gRPC认证的多种方式实践

gRPC认证的多种方式实践

gRPC安全认证介绍

  • gRPC被设计成可以利用插件的形式支持多种授权认证机制,你可以采用自己喜欢的,简单的,认为方便的一种方式,选择权在用户手里
  • 支持的授权认证机制如下
    1. SSL/TLS认证
    2. 自定义Token认证
  • SSL/TLS的概念可以参考下面的文章
  • https://www.techug.com/post/https-ssl-tls.html

SSL/TLS认证方式

  • 首先通过openssl生成证书和私钥,命令如下
//生成私钥
openssl genrsa -out server.key 2048

//生成证书
openssl req -new -x509 -sha256 -key server.key  -out server.crt -days 36500

//按照提示输入如下信息
国家名称
Country Name (2 letter code) [AU]:
//省名称
State or Province Name (full name) [Some-State]:
//城市名称
Locality Name (eg, city) []:
//理解为公司名称
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
//理解为你所在部门的名称
Organizational Unit Name (eg, section) []:
//你的服务器名称(网站名称)
Common Name (e.g. server FQDN or YOUR name) []:
//联系邮箱
Email Address []:
  • 服务端如下
func StartServer() {

   lis, err := net.Listen("tcp", "127.0.0.1:8090")
   if err != nil {
      log.Fatalf("failed to listen: %v", err)
   }
   // TLS认证
   // 两个入参分别是 (certFile, keyFile string)
   // 自签名证书文件和私钥文件
   creds, err := credentials.NewServerTLSFromFile("cert", "key")
   //创建grpcServer传入证书
   gRpcServer := grpc.NewServer(grpc.Creds(creds))
   pb.RegisterHelloServiceServer(gRpcServer, &HelloServiceServer{})
   gRpcServer.Serve(lis)
}
  • 客户端如下
func StartClient() {
   // TLS认证
   creds, err := credentials.NewClientTLSFromFile("cert", "ServerName")
   //连接服务器
   conn, err := grpc.Dial("127.0.0.1:8090",grpc.WithTransportCredentials(creds) )
   if err != nil{
      fmt.Println(err)
      return
   }
   c := pb.NewHelloServiceClient(conn)
   //
   ctx, cancel := context.WithTimeout(context.Background(), time.Second)
   defer cancel()
   r, err := c.HelloWorldClientAndServerStream(ctx, grpc.EmptyCallOption{})
   if err != nil {
        log.Fatalf("%v", err)
        return
   }
   r.Send(&pb.HelloRequest{Request: "my is golang gRpc client "})
   r.CloseSend()
}
  • 如上就开启了gRPC的TLS认证

Token认证

  • 我们先看一个gRPC提供我们的一个接口,这个接口中有两个方法,接口位于credentials 包下,这个接口需要客户端来实现
  • 第一个方法作用是获取元数据信息,也就是客户端提供的key,value对,context用于控制超时和取消,uri是请求入口处的uri
  • 第二个方法的作用是否需要基于 TLS 认证进行安全传输,如果返回值是true,则必须加上TLS验证,返回值是false则不用
type PerRPCCredentials interface {
    GetRequestMetadata(ctx context.Context, uri ...string) 
        (map[string]string, error)
    RequireTransportSecurity() bool
}
  • 客户端端实现接口,代码如下
//自定义token认证
type CustomerTokenAuth struct {
}
//获取元数据
func (c CustomerTokenAuth) GetRequestMetadata(ctx context.Context, 
   uri...string) (map[string]string, error) {

   return map[string]string{
      "appId":  "master",
      "appkey": "1aqfs5g456j",
   }, nil
}
//是否开启传输安全 TLS
func (c CustomerTokenAuth) RequireTransportSecurity() bool {
   return false
}
  • 客户端按照如下方式使用
var opts []grpc.DialOption
//grpc.WithInsecure()这个是一定要添加的,代表开启安全的选项
opts =append(opts,grpc.WithInsecure())
//添加自定义token验证
opts = append(opts,grpc.WithPerRPCCredentials(new(CustomerTokenAuth)))
//连接服务端
conn, err := grpc.Dial("127.0.0.1:8090",opts...)
  • 服务端按照如下方式校验,当然我们也可以使用拦截器的形式对每个方法进行拦截,而不是像如下在每个方法中硬编码似的。
type HelloServiceServer struct {
}
//这是服务端实现的一个方法
func (*HelloServiceServer2) HelloWorld(ctx context.Context, 
   req *pb.HelloRequest) (*pb.HelloResponse, error) {
   //获取元数据信息
   md,ok := metadata.FromIncomingContext(ctx)
   if !ok {
      return nil,errors.New("未传输token")
   }
   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 != "123" || appkey != "456" {
        return nil, errors.New("token传输不正确")
   }
   return &pb.HelloResponse{Response: "hello my is gRpcServer"}, nil
}

总结

  • gRPC将各种认证方式浓缩统一到一个凭证(credentials)上,可以单独使用一种凭证,比如只使用TLS凭证或者只使用自定义凭证,也可以多种凭证组合,gRPC提供统一的API验证机制,使研发人员使用方便,这也是gRPC设计的巧妙之处

本文分享自微信公众号 - GoLang那点事(aweiaichitudou),作者:那小子阿伟

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-09-08

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • gRPC认证的多种方式实践(排版整理)

    gRPC被设计成可以利用插件的形式支持多种授权认证机制,你可以采用自己喜欢的,简单的,认为方便的一种方式,选择权在用户手里

    阿伟
  • gRPC之GoLang入门HelloWord(排版整理)

    这篇文章里我们要实现一个基于GoLang编程语言的gRPC的客户端与服务端通信的HelloWorld案例,喜欢grpc的一定要去实践。

    阿伟
  • 微服务-高并发下接口如何做到优雅的限流

    通俗的来讲,一根管子往池塘注水,池塘底部有一个口子往外出水,当注水的速度过快时,池塘的水会溢出,此时,我们的做法换根小管子注水或者把注水管子的口堵住一半,这就是...

    阿伟
  • 开始食用grpc(之一)

    转载请注明出处:https://www.cnblogs.com/funnyzpc/p/9501353.html

    上帝
  • 用TS+GraphQL查询SpaceX火箭发射数据[每日前端夜话0x81]

    近一两年来 GraphQL 和 TypeScript 的使用都程爆发式增长,当两者与React结合使用时,它们可以为开发人员提供理想的开发体验。

    疯狂的技术宅
  • 爬虫智能解析库 Readability 和 Newspaper 的用法

    舆情爬虫是网络爬虫一个比较重要的分支,舆情爬虫往往需要爬虫工程师爬取几百几千个新闻站点。比如一个新闻页面我们需要爬取其标题、正文、时间、作者等信息,如果用传统的...

    崔庆才
  • 35行代码搞定事件研究法(下)

    Hello亲爱的小伙伴们,上期已经讲到如何对单一事件日计算超额收益,本期将会教大家如何针对多个股票多个事件日计算超额收益,Let's go!

    用户7652506
  • python批量修改xml属性的实现方式

    今天来说说xml那些事儿.如何批量修改指定文件夹下的xml文件的指定属性.分三步走,首先,我们先看看如何读写单个

    砸漏
  • LeetCode 344 Reverse String

    一份执着✘
  • Docker版的Webug4.0漏洞靶场

    WeBug名称定义为"我们的漏洞"靶场环境 ,基础环境是基于PHP/mysql制作搭建而成,中级环境与高级环境分别都是由互联网漏洞事件而收集的漏洞存在的操作环境...

    南宫十六

扫码关注云+社区

领取腾讯云代金券