1. RPC 调用安全策略
1.1 严峻的安全形势
近年来,个人信息泄漏和各种信息安全事件层出不穷,个人信息安全以及隐私数据保护面临严峻的挑战。
很多国家已经通过立法的方式保护个人信息和数据安全,例如我国 2016 年 11 月 7 日出台、2017 年 6 月 1 日正式实施的《网络安全法》,以及 2016 年 4 月 14 日欧盟通过的《一般数据保护法案》(GDP R),该法案将于 2018 年 5 月 25 日正式生效。
GDPR 的通过意味着欧盟对个人信息保护及其监管达到了前所未有的高度,堪称史上最严格的数据保护法案。
作为企业内部各系统、模块之间调用的通信框架,即便是内网通信,RPC 调用也需要考虑安全性,RPC 调用安全主要涉及如下三点:
个人 / 企业敏感数据加密:例如针对个人的账号、密码、手机号等敏感信息进行加密传输,打印接口日志时需要做数据模糊化处理等,不能明文打印;
对调用方的身份认证:调用来源是否合法,是否有访问某个资源的权限,防止越权访问;
数据防篡改和完整性:通过对请求参数、消息头和消息体做签名,防止请求消息在传输过程中被非法篡改。
1.2 敏感数据加密传输
1.2.1 基于 SSL/TLS 的通道加密
当存在跨网络边界的 RPC 调用时,往往需要通过 TLS/SSL 对传输通道进行加密,以防止请求和响应消息中的敏感数据泄漏。跨网络边界调用场景主要有三种:
后端微服务直接开放给端侧,例如手机 App、TV、多屏等,没有统一的 API Gateway/SLB 做安全接入和认证;
后端微服务直接开放给 DMZ 部署的管理或者运维类 Portal;
除了跨网络之外,对于一些安全等级要求比较高的业务场景,即便是内网通信,只要跨主机 /VM/ 容器通信,都强制要求对传输通道进行加密。在该场景下,即便只存在内网各模块的 RPC 调用,仍然需要做 SSL/TLS。
使用 SSL/TLS 的典型场景如下所示:
目前使用最广的 SSL/TLS 工具 / 类库就是 OpenSSL,它是为网络通信提供安全及数据完整性的一种安全协议,囊括了主要的密码算法、常用的密钥和证书封装管理功能以及 SSL 协议。
多数 SSL 加密网站是用名为 OpenSSL 的开源软件包,由于这也是互联网应用最广泛的安全传输方法,被网银、在线支付、电商网站、门户网站、电子邮件等重要网站广泛使用。
1.2.2 针对敏感数据的单独加密
有些 RPC 调用并不涉及敏感数据的传输,或者敏感字段占比较低,为了最大程度的提升吞吐量,降低调用时延,通常会采用 HTTP/TCP + 敏感字段单独加密的方式,既保障了敏感信息的传输安全,同时也降低了采用 SSL/TLS 加密通道带来的性能损耗,对于 JDK 原生的 SSL 类库,这种性能提升尤其明显。
它的工作原理如下所示:
通常使用 Handler 拦截机制,对请求和响应消息进行统一拦截,根据注解或者加解密标识对敏感字段进行加解密,这样可以避免侵入业务。
采用该方案的缺点主要有两个:
对敏感信息的识别可能存在偏差,容易遗漏或者过度保护,需要解读数据和隐私保护方面的法律法规,而且不同国家对敏感数据的定义也不同,这会为识别带来很多困难;
接口升级时容易遗漏,例如开发新增字段,忘记识别是否为敏感数据。
1.3 认证和鉴权
RPC 的认证和鉴权机制主要包含两点:
事实上,并非所有的 RPC 调用都必须要做认证和鉴权,例如通过 API Gateway 网关接入的流量,已经在网关侧做了鉴权和身份认证,对来自网关的流量 RPC 服务端就不需要重复鉴权。
另外,一些对安全性要求不太高的场景,可以只做认证而不做细粒度的鉴权。
1.3.1 身份认证
内部 RPC 调用的身份认证场景,主要有如下两大类:
防止对方知道服务提供者的地址之后,绕过注册中心 / 服务路由策略直接访问 RPC 服务提供端;
RPC 服务只想供内部模块调用,不想开放给其它业务系统使用(双方网络是互通的)。
身份认证的方式比较多,例如 HTTP Basic Authentication、OAuth2 等,比较简单使用的是令牌认证(Token)机制,它的工作原理如下所示:
工作原理如下:
RPC 客户端和服务端通过 HTTPS 与注册中心连接,做双向认证,以保证客户端和服务端与注册中心之间的安全;
服务端生成 Token 并注册到注册中心,由注册中心下发给订阅者。通过订阅 / 发布机制,向 RPC 客户端做 Token 授权;
服务端开启身份认证,对 RPC 调用进行 Token 校验,认证通过之后才允许调用后端服务接口。
1.3.2 权限管控
身份认证可以防止非法调用,如果需要对调用方进行更细粒度的权限管控,则需要做对 RPC 调用做鉴权。例如管理员可以查看、修改和删除某个后台资源,而普通用户只能查看资源,不能对资源做管理操作。
在 RPC 调用领域比较流行的是基于 OAuth2.0 的权限认证机制,它的工作原理如下:
OAuth2.0 的认证流程如下:
客户端向资源拥有者申请授权(例如携带用户名 + 密码等证明身份信息的凭证);
资源拥有者对客户端身份进行校验,通过之后同意授权;
客户端使用步骤 2 的授权凭证,向认证服务器申请资源访问令牌(access token);
认证服务器对授权凭证进行合法性校验,通过之后,颁发 access token;
客户端携带 access token(通常在 HTTP Header 中)访问后端资源,例如发起 RPC 调用;
服务端对 access token 合法性进行校验(是否合法、是否过期等),同时对 token 进行解析,获取客户端的身份信息以及对应的资源访问权限列表,实现对资源访问权限的细粒度管控;
access token 校验通过,返回资源信息给客户端。
步骤 2 的用户授权,有四种方式:
授权码模式(authorization code)
密码模式(resource owner password credentials)
客户端模式(client credentials)
需要指出的是,OAuth 2.0 是一个规范,不同厂商即便遵循该规范,实现也可能会存在细微的差异。大部分厂商在采用 OAuth 2.0 的基础之上,往往会衍生出自己特有的 OAuth 2.0 实现。
对于 access token,为了提升性能,RPC 服务端往往会缓存,不需要每次调用都与 AS 服务器做交互。同时,access token 是有过期时间的,根据业务的差异,过期时间也会不同。客户端在 token 过期之前,需要刷新 Token,或者申请一个新的 Token。
考虑到 access token 的安全,通常选择 SSL/TLS 加密传输,或者对 access token 单独做加密,防止 access token 泄漏。
1.4 数据完整性和一致性
RPC 调用,除了数据的机密性和有效性之外,还有数据的完整性和一致性需要保证,即如何保证接收方收到的数据与发送方发出的数据是完全相同的。
利用消息摘要可以保障数据的完整性和一致性,它的特点如下: