微服务架构的认证与鉴权

微服务很酷,但流量在各服务间欢快穿梭的背后可能隐藏着重大安全隐患,黑客也许只需要通过一个点,就能将整个体系击溃。

相比单体应用,在微服务架构的身份认证和鉴权需要考虑的点要多许多。在单体应用中的只有两个对象,即用户与整体的系统,相对简单。

在微服务架构中,对象可能有用户、API 网关、身份认证鉴权服务和其他服务。系统由多个服务组成,并且为了更好的伸缩性,每个服务都应该是无状态的,而服务的对外网络也许并不是完全隔离的,服务间是不可信的,服务间也需要认证和鉴权。

为了保持微服务的简洁轻量,可以将身份认证和鉴权可以单独的拆分出来作为一个或两个独立的服务,由这些服务负责授权,其他服务可以根据用户携带的令牌进行认证。当然,若是能做到完全隔离,并且服务间完全可信,也可以在 API 网关统一解决认证和鉴权,能减少各服务的关注点,把注意力集中在业务本身。服务间通信有一定的成本,如果每个请求过来,除了 API 网关以外,请求涉及到服务都调用一次鉴权服务,这会大大增加鉴权服务的压力,可能会成为系统瓶颈并带来隐患,下面为了平衡安全性和性能来进一步分析选型。

身份认证

认证(Authentication):验证你是不是你。

身份认证大致可分为以下三种:

  • HTTP Basic
  • Session
  • OAuth2 + JWT

HTTP Basic、HTTP Digest 这类的特点是用户不持有服务端下发的凭证。用户直接将用户名和密码经过一定处理(可逆/不可逆),发送到服务端,服务端使用同样的方法,对比用户名和密码。这种方式可以在安全性要求不高和黑客难以嗅探的情况下使用。

Session 是最常用的认证方式,特点是用户持有一个不可被第三方验证的凭证。用户登录成功后,服务端将用户信息写入 Session,并向客户端返回一个难以被猜解或穷举的 SessionID,存储在客户端 Cookie 中。用户的后续每个请求将携带上这个 SessionID,服务端以此查询对应 Session。然而在分布式系统中,不能将 Session 仅存放在一台节点上,需要改造成无状态,可以使用分布式 Session 解决。

这里的 Token 方案是指第三方可验证的Token,认证方无需再去查询缓存或数据库,仅通过数字签名即可验证,如 JWT。JWT 常用的方式是 HS256 (HMAC with SHA-256),使用一个对称不可逆的算法对用户授权信息做数字签名,各服务都持有一个共享私钥,可签名,亦可校验。每个接入服务能控制整个认证体系,这个私钥一旦泄漏,身份认证将形同虚设。于是 JWT 还有另一种校验算法,RS256 (RSA Signature with SHA-256),使用非对称的算法,认证服务签名时使用私钥(只有认证服务持有)签名,其他服务持有公钥,只能校验用户凭证的有效性,而不能伪造凭证。这样可以将风险缩小,把签名权限控制在一个服务中。

鉴权

鉴权(Authorization):鉴定你能干些什么。

在 JWT 的方案中,由于用户权限已经写在了 Token 上了,如果用户权限发生变更,用户要是不重新生成 Token,权限还是原来的不变。要实现权限的实时变更,Session 是很好的方法,发生权限变更事件时,鉴权服务响应事件,只需要更新 Session 和数据库中的权限。如果将两者结合起来呢,与浏览器鉴权的方式为 Session,请求先经过 API 网关,API 网关通过 SessionID 向鉴权服务换取 JWT,如用户无权限,可以直接拒绝请求。API 网关将 JWT (RS256) 放置 Authorization 头,再转发到下游服务,下游服务使用公钥校验签名有效性,取出授权信息,完成鉴权。

总结

平衡了系统的安全性和性能,可使用分布式 Session(对用户) 与 OAuth2 + JWT (RS256)(对服务)的方案。

Leave a Reply

Your email address will not be published. Required fields are marked *