作者:
henry_czh(授权转载,勿二次转载)
来源:https://juejin.im/post/6854573218884222989
前言
上一篇文章讲述了RPC服务的概念和gRPC的基本使用、proto语法的使用教程。然而在我们真正把gRPC服务部署到生产环境上的时候,会遇到很多问题,首选要考虑的就是协议的数据认证问题,其次,gRPC也支持流式通信的模式,本篇文章会做一个介绍说明。
RPC的身份认证
RPC服务一般在服务内网使用,但是也有存在于外网的RPC服务,但是不论是哪一种RPC服务,走http2.0还是其他基于TCP实现socket的协议,在部署生产环境的时候还是需要增加身份加密认证机制的,客户端与服务端需要做一个可信任的认证,以保障数据的安全性。
RPC服务一般的加密认证方法
基于 SSL/TLS 的通道加密 通常身份认证机制是通过 TLS/SSL 对传输通道进行加密,以防止请求和响应消息中的敏感数据泄漏。使用的场景主要有三种:
后端微服务直接开放给端侧,例如手机 App、TV、多屏等,没有统一的 API Gateway/SLB 做安全接入和认证;
后端微服务直接开放给 DMZ 部署的管理或者运维类 Portal;
后端微服务直接开放给第三方合作伙伴 / 渠道。除了上述常用的跨网络场景之外,对于一些安全等级要求比较高的业务场景,即便是内网通信,只要跨主机 /VM/ 容器通信,都强制要求对传输通道进行加密。在该场景下,即便只存在内网各模块的 RPC 调用,仍然需要做 SSL/TLS。
使用 SSL/TLS 的典型场景如下所示:
目前使用最广的 SSL/TLS 工具 / 类库就是 OpenSSL,它是为网络通信提供安全及数据完整性的一种安全协议,囊括了主要的密码算法、常用的密钥和证书封装管理功能以及 SSL 协议。
多数 SSL 加密网站是用名为 OpenSSL 的开源软件包,由于这也是互联网应用最广泛的安全传输方法,被网银、在线支付、电商网站、门户网站、电子邮件等重要网站广泛使用。
针对敏感数据的单独加密 有些 RPC 调用并不涉及敏感数据的传输,或者敏感字段占比较低,为了最大程度的提升吞吐量,降低调用时延,通常会采用 HTTP/TCP + 敏感字段单独加密的方式,既保障了敏感信息的传输安全,同时也降低了采用 SSL/TLS 加密通道带来的性能损耗,对于 JDK 原生的 SSL 类库,这种性能提升尤其明显。
它的工作原理如下所示:
通常使用 Handler 拦截机制,对请求和响应消息进行统一拦截,根据注解或者加解密标识对敏感字段进行加解密,这样可以避免侵入业务。
采用该方案的缺点主要有两个:
对敏感信息的识别可能存在偏差,容易遗漏或者过度保护,需要解读数据和隐私保护方面的法律法规,而且不同国家对敏感数据的定义也不同,这会为识别带来很多困难;
接口升级时容易遗漏,例如开发新增字段,忘记识别是否为敏感数据。
gRPC的加密认证方法
对于gRPC,SSL/TLS协议也是基本的身份加密认证方法,SSL/TLS协议采用公钥加密法,客户端向服务器端索要公钥,然后用公钥加密信息,服务器收到密文后,用自己的私钥解密。
SSL/TLS SSL/TLS 分为单向认证和双向认证,在实际业务中,单向认证使用较多,即客户端认证服务端,服务端不认证客户端。认证流程如下:
客户端向服务端传送客户端 SSL 协议的版本号、支持的加密算法种类、产生的随机数,以及其它可选信息;
服务端返回握手应答,向客户端传送确认 SSL 协议的版本号、加密算法的种类、随机数以及其它相关信息;
服务端向客户端发送自己的公钥;
客户端对服务端的证书进行认证,服务端的合法性校验包括:证书是否过期、发行服务器证书的 CA 是否可靠、发行者证书的公钥能否正确解开服务器证书的“发行者的数字签名”、服务器证书上的域名是否和服务器的实际域名相匹配等;
客户端随机产生一个用于后面通讯的“对称密码”,然后用服务端的公钥对其加密,将加密后的“预主密码”传给服务端;
服务端将用自己的私钥解开加密的“预主密码”,然后执行一系列步骤来产生主密码;
客户端向服务端发出信息,指明后面的数据通讯将使用主密码为对称密钥,同时通知服务器客户端的握手过程结束;
服务端向客户端发出信息,指明后面的数据通讯将使用主密码为对称密钥,同时通知客户端服务器端的握手过程结束;
SSL 的握手部分结束,SSL 安全通道建立,客户端和服务端开始使用相同的对称密钥对数据进行加密,然后通过 Socket 进行传输。<