资讯专栏INFORMATION COLUMN

带入gRPC:对 RPC 方法做自定义认证

wh469012917 / 2132人阅读

摘要:带入对方法做自定义认证原文地址带入对方法做自定义认证项目地址前言在前面的章节中,我们介绍了两种证书算一种可全局认证的方法证书认证基于的证书认证而在实际需求中,常常会对某些模块的方法做特殊认证或校验。

带入gRPC:对 RPC 方法做自定义认证

原文地址:带入gRPC:对 RPC 方法做自定义认证
项目地址:https://github.com/EDDYCJY/go...

前言

在前面的章节中,我们介绍了两种(证书算一种)可全局认证的方法:

TLS 证书认证

基于 CA 的 TLS 证书认证

Unary and Stream interceptor

而在实际需求中,常常会对某些模块的 RPC 方法做特殊认证或校验。今天将会讲解、实现这块的功能点

课前知识

</>复制代码

  1. type PerRPCCredentials interface {
  2. GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error)
  3. RequireTransportSecurity() bool
  4. }

在 gRPC 中默认定义了 PerRPCCredentials,它就是本章节的主角,是 gRPC 默认提供用于自定义认证的接口,它的作用是将所需的安全认证信息添加到每个 RPC 方法的上下文中。其包含 2 个方法:

GetRequestMetadata:获取当前请求认证所需的元数据(metadata)

RequireTransportSecurity:是否需要基于 TLS 认证进行安全传输

目录结构

新建 simple_token_server/server.go 和 simple_token_client/client.go,目录结构如下:

</>复制代码

  1. go-grpc-example
  2. ├── client
  3. │   ├── simple_client
  4. │   ├── simple_http_client
  5. │   ├── simple_token_client
  6. │   └── stream_client
  7. ├── conf
  8. ├── pkg
  9. ├── proto
  10. ├── server
  11. │   ├── simple_http_server
  12. │   ├── simple_server
  13. │   ├── simple_token_server
  14. │   └── stream_server
  15. └── vendor
gRPC Client

</>复制代码

  1. package main
  2. import (
  3. "context"
  4. "log"
  5. "google.golang.org/grpc"
  6. "github.com/EDDYCJY/go-grpc-example/pkg/gtls"
  7. pb "github.com/EDDYCJY/go-grpc-example/proto"
  8. )
  9. const PORT = "9004"
  10. type Auth struct {
  11. AppKey string
  12. AppSecret string
  13. }
  14. func (a *Auth) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) {
  15. return map[string]string{"app_key": a.AppKey, "app_secret": a.AppSecret}, nil
  16. }
  17. func (a *Auth) RequireTransportSecurity() bool {
  18. return true
  19. }
  20. func main() {
  21. tlsClient := gtls.Client{
  22. ServerName: "go-grpc-example",
  23. CertFile: "../../conf/server/server.pem",
  24. }
  25. c, err := tlsClient.GetTLSCredentials()
  26. if err != nil {
  27. log.Fatalf("tlsClient.GetTLSCredentials err: %v", err)
  28. }
  29. auth := Auth{
  30. AppKey: "eddycjy",
  31. AppSecret: "20181005",
  32. }
  33. conn, err := grpc.Dial(":"+PORT, grpc.WithTransportCredentials(c), grpc.WithPerRPCCredentials(&auth))
  34. ...
  35. }

在 Client 端,重点实现 type PerRPCCredentials interface 所需的方法,关注两点即可:

struct Auth:GetRequestMetadata、RequireTransportSecurity

grpc.WithPerRPCCredentials

Server

</>复制代码

  1. package main
  2. import (
  3. "context"
  4. "log"
  5. "net"
  6. "google.golang.org/grpc"
  7. "google.golang.org/grpc/codes"
  8. "google.golang.org/grpc/metadata"
  9. "google.golang.org/grpc/status"
  10. "github.com/EDDYCJY/go-grpc-example/pkg/gtls"
  11. pb "github.com/EDDYCJY/go-grpc-example/proto"
  12. )
  13. type SearchService struct {
  14. auth *Auth
  15. }
  16. func (s *SearchService) Search(ctx context.Context, r *pb.SearchRequest) (*pb.SearchResponse, error) {
  17. if err := s.auth.Check(ctx); err != nil {
  18. return nil, err
  19. }
  20. return &pb.SearchResponse{Response: r.GetRequest() + " Token Server"}, nil
  21. }
  22. const PORT = "9004"
  23. func main() {
  24. ...
  25. }
  26. type Auth struct {
  27. appKey string
  28. appSecret string
  29. }
  30. func (a *Auth) Check(ctx context.Context) error {
  31. md, ok := metadata.FromIncomingContext(ctx)
  32. if !ok {
  33. return status.Errorf(codes.Unauthenticated, "自定义认证 Token 失败")
  34. }
  35. var (
  36. appKey string
  37. appSecret string
  38. )
  39. if value, ok := md["app_key"]; ok {
  40. appKey = value[0]
  41. }
  42. if value, ok := md["app_secret"]; ok {
  43. appSecret = value[0]
  44. }
  45. if appKey != a.GetAppKey() || appSecret != a.GetAppSecret() {
  46. return status.Errorf(codes.Unauthenticated, "自定义认证 Token 无效")
  47. }
  48. return nil
  49. }
  50. func (a *Auth) GetAppKey() string {
  51. return "eddycjy"
  52. }
  53. func (a *Auth) GetAppSecret() string {
  54. return "20181005"
  55. }

在 Server 端就更简单了,实际就是调用 metadata.FromIncomingContext 从上下文中获取 metadata,再在不同的 RPC 方法中进行认证检查

验证

重新启动 server.go 和 client.go,得到以下结果:

</>复制代码

  1. $ go run client.go
  2. 2018/10/05 20:59:58 resp: gRPC Token Server

修改 client.go 的值,制造两者不一致,得到无效结果:

</>复制代码

  1. $ go run client.go
  2. 2018/10/05 21:00:05 client.Search err: rpc error: code = Unauthenticated desc = invalid token
  3. exit status 1
一个个加太麻烦

我相信你肯定会问一个个加,也太麻烦了吧?有这个想法的你,应当把 type PerRPCCredentials interface 做成一个拦截器(interceptor)

总结

本章节比较简单,主要是针对 RPC 方法的自定义认证进行了介绍,如果是想做全局的,建议是举一反三从拦截器下手哦

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/29522.html

相关文章

  • 带入gRPCgRPC及相关介绍

    摘要:带入及相关介绍原文地址带入及相关介绍项目地址作为开篇章,将会介绍相关的一些知识。 带入gRPC:gRPC及相关介绍 原文地址:带入gRPC:gRPC及相关介绍 项目地址:go-grpc-example 作为开篇章,将会介绍 gRPC 相关的一些知识。简单来讲 gRPC 是一个 基于 HTTP/2 协议设计的 RPC 框架,它采用了 Protobuf 作为 IDL 你是否有过疑惑,它们都...

    AJie 评论0 收藏0
  • 带入gRPCgRPC及相关介绍

    摘要:原文地址带入及相关介绍项目地址作为开篇章,将会介绍相关的一些知识。 原文地址:带入gRPC:gRPC及相关介绍 项目地址:go-grpc-example 作为开篇章,将会介绍 gRPC 相关的一些知识。简单来讲 gRPC 是一个 基于 HTTP/2 协议设计的 RPC 框架,它采用了 Protobuf 作为 IDL 你是否有过疑惑,它们都是些什么?本文将会介绍一些常用的知识和概念,更详...

    y1chuan 评论0 收藏0
  • 带入gRPCgRPC Streaming, Client and Server

    摘要:带入原文地址带入项目地址前言本章节将介绍的流式,分为三种类型服务器端流式客户端流式双向流式流任何技术,因为有痛点,所以才有了存在的必要性。这一次性涉及的数据量确实大在同步完成后,也有人马上会去查阅数据,为了新的一天筹备。 带入gRPC:gRPC Streaming, Client and Server 原文地址:带入gRPC:gRPC Streaming, Client and Ser...

    wayneli 评论0 收藏0
  • 带入gRPC:基于 CA 的 TLS 证书认证

    摘要:带入基于的证书认证原文地址带入基于的证书认证项目地址前言在上一章节中,我们提出了一个问题。其遵守标准根证书根证书是属于根证书颁发机构的公钥证书。目标是基于进行认证 带入gRPC:基于 CA 的 TLS 证书认证 原文地址:带入gRPC:基于 CA 的 TLS 证书认证项目地址:https://github.com/EDDYCJY/go... 前言 在上一章节中,我们提出了一个问题。就是...

    史占广 评论0 收藏0
  • 带入gRPC:分布式链路追踪 gRPC-Opentracing-Zipkin

    摘要:带入分布式链路追踪原文地址带入分布式链路追踪项目地址前言在实际应用中,你做了那么多端,写了个方法。想看看方法的指标,却无处下手本文将通过搭建一个分布式链路追踪系统来实现查看整个系统的链路性能等指标 带入gRPC:分布式链路追踪 gRPC + Opentracing + Zipkin 原文地址:带入gRPC:分布式链路追踪 gRPC + Opentracing + Zipkin项目地址:...

    BicycleWarrior 评论0 收藏0

发表评论

0条评论

wh469012917

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<