烟台征婚网:Go gRPC进阶-TLS认证+自定义方式认证(七)

admin 6个月前 (04-16) 科技 37 0

前言

前面篇章的gRPC都是明文传输的,容易被窜改数据。本章将先容如作甚gRPC添加平安机制,包罗TLS证书认证和Token认证。

TLS证书认证

什么是TLS

TLS(Transport Layer Security,平安传输层),TLS是确立在传输层TCP协议之上的协议,服务于应用层,它的前身是SSL(Secure Socket Layer,平安套接字层),它实现了将应用层的报文举行加密后再交由TCP举行传输的功效。

TLS的作用

TLS协议主要解决如下三个网络平安问题

  • 保密(message privacy),保密通过加密encryption实现,所有信息都加密传输,第三方无法嗅探;
  • 完整性(message integrity),通过MAC校验机制,一旦被窜改,通讯双方会马上发现;
  • 认证(mutual authentication),双方认证,双方都可以配备证书,防止身份被冒充;

天生私钥

天生RSA私钥:openssl genrsa -out server.key 2048

天生RSA私钥,下令的最后一个参数,将指定天生密钥的位数,若是没有指定,默认512

天生ECC私钥:openssl ecparam -genkey -name secp384r1 -out server.key

天生ECC私钥,下令为椭圆曲线密钥参数天生及操作,本文中ECC曲线选择的是secp384r1

天生公钥

openssl req -new -x509 -sha256 -key server.key -out server.pem -days 3650

openssl req:天生自署名证书,-new指天生证书请求、-sha256指使用sha256加密、-key指定私钥文件、-x509指输出证书、-days 3650为有效期

今后则输入证书拥有者信息

Country Name (2 letter code) [AU]:CN
State or Province Name (full name) [Some-State]:XxXx
Locality Name (eg, city) []:XxXx
Organization Name (eg, company) [Internet Widgits Pty Ltd]:XX Co. Ltd
Organizational Unit Name (eg, section) []:Dev
Common Name (e.g. server FQDN or YOUR name) []:go-grpc-example
Email Address []:xxx@xxx.com

服务端构建TLS证书并认证

func main() {
	// 监听内陆端口
	listener, err := net.Listen(Network, Address)
	if err != nil {
		log.Fatalf("net.Listen err: %v", err)
	}
	// 从输入证书文件和密钥文件为服务端组织TLS凭证
	creds, err := credentials.NewServerTLSFromFile("../pkg/tls/server.pem", "../pkg/tls/server.key")
	if err != nil {
		log.Fatalf("Failed to generate credentials %v", err)
	}
	// 新建gRPC服务器实例,并开启TLS认证
	grpcServer := grpc.NewServer(grpc.Creds(creds))
	// 在gRPC服务器注册我们的服务
	pb.RegisterSimpleServer(grpcServer, &SimpleService{})
	log.Println(Address + " net.Listing whth TLS and token...")
	//用服务器 Serve() 方式以及我们的端口信息区实现壅闭守候,直到历程被杀死或者 Stop() 被挪用
	err = grpcServer.Serve(listener)
	if err != nil {
		log.Fatalf("grpcServer.Serve err: %v", err)
	}
}
  • credentials.NewServerTLSFromFile:从输入证书文件和密钥文件为服务端组织TLS凭证
  • grpc.Creds:返回一个ServerOption,用于设置服务器毗邻的凭证。

完整server.go代码

客户端设置TLS毗邻

var grpcClient pb.SimpleClient

func main() {
	//从输入的证书文件中为客户端组织TLS凭证
	creds, err := credentials.NewClientTLSFromFile("../pkg/tls/server.pem", "go-grpc-example")
	if err != nil {
		log.Fatalf("Failed to create TLS credentials %v", err)
	}
	// 毗邻服务器
	conn, err := grpc.Dial(Address, grpc.WithTransportCredentials(creds))
	if err != nil {
		log.Fatalf("net.Connect err: %v", err)
	}
	defer conn.Close()

	// 确立gRPC毗邻
	grpcClient = pb.NewSimpleClient(conn)
}
  • credentials.NewClientTLSFromFile:从输入的证书文件中为客户端组织TLS凭证。
  • grpc.WithTransportCredentials:设置毗邻级别的平安凭证(例如,TLS/SSL),返回一个DialOption,用于毗邻服务器。

完整client.go代码

到这里,已经完成TLS证书认证了,gRPC传输不再是明文传输。此外,添加自界说的验证方式能使gRPC相对更平安。下面以Token认证为例,先容gRPC若何添加自界说验证方式。

Token认证

客户端发请求时,添加Token到上下文context.Context中,服务器接收到请求,先从上下文中获取Token验证,验证通过才举行下一步处置。

客户端请求添加Token到上下文中

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

gRPC 中默认界说了 PerRPCCredentials,是提供用于自界说认证的接口,它的作用是将所需的平安认证信息添加到每个RPC方式的上下文中。其包罗 2 个方式:

  • GetRequestMetadata:获取当前请求认证所需的元数据
  • RequireTransportSecurity:是否需要基于 TLS 认证举行平安传输

接下来我们实现这两个方式

// Token token认证
type Token struct {
	AppID     string
	AppSecret string
}

// GetRequestMetadata 获取当前请求认证所需的元数据(metadata)
func (t *Token) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) {
	return map[string]string{"app_id": t.AppID, "app_secret": t.AppSecret}, nil
}

// RequireTransportSecurity 是否需要基于 TLS 认证举行平安传输
func (t *Token) RequireTransportSecurity() bool {
	return true
}

然后再客户端中挪用Dial时添加自界说验证方式进去

//构建Token
	token := auth.Token{
		AppID:     "grpc_token",
		AppSecret: "123456",
	}
	// 毗邻服务器
	conn, err := grpc.Dial(Address, grpc.WithTransportCredentials(creds), grpc.WithPerRPCCredentials(&token))

完整client.go代码

服务端验证Token

首先需要从上下文中获取元数据,然后从元数据中剖析Token举行验证

// Check 验证token
func Check(ctx context.Context) error {
	//从上下文中获取元数据
	md, ok := metadata.FromIncomingContext(ctx)
	if !ok {
		return status.Errorf(codes.Unauthenticated, "获取Token失败")
	}
	var (
		appID     string
		appSecret string
	)
	if value, ok := md["app_id"]; ok {
		appID = value[0]
	}
	if value, ok := md["app_secret"]; ok {
		appSecret = value[0]
	}
	if appID != "grpc_token" || appSecret != "123456" {
		return status.Errorf(codes.Unauthenticated, "Token无效: app_id=%s, app_secret=%s", appID, appSecret)
	}
	return nil
}
  • metadata.FromIncomingContext:从上下文中获取元数据

完整server.go代码

总结

本篇先容如作甚gRPC添加TLS证书认证和自界说认证,从而让gRPC更平安。然而上面Token认证的代码中,服务端验证Token时,需要在每个方式前添加Token验证,这样对照贫苦。下篇将先容若何使用gRPC拦截器,取消掉这个重复步骤。

教程源码地址:https://github.com/Bingjian-Zhu/go-grpc-example

参考:

  • https://www.jianshu.com/p/1fc7130eb2c2
  • https://segmentfault.com/a/1190000007933303
  • https://eddycjy.com/posts/go/grpc/2018-10-07-grpc-tls/
,

Sunbet

www.1888ss.com秉承以客为先的理念,多年运营、专业团队、专注服务、值得信赖。

dafa888体育声明:该文看法仅代表作者自己,与本平台无关。转载请注明:烟台征婚网:Go gRPC进阶-TLS认证+自定义方式认证(七)

网友评论

  • (*)

最新评论

文章归档

站点信息

  • 文章总数:738
  • 页面总数:0
  • 分类总数:8
  • 标签总数:1179
  • 评论总数:436
  • 浏览总数:22043