微服务安全(一)
前言
在微服务架构中一个应用通常会被拆分成一系列的微服务,这些微服务需要对访问者进行身份认证及鉴权,而此时进行应用安全管理,针对的不仅仅是用户请求,还包含其他微服务的调用。这时候安全管理由原来单一的“用户-服务”场景,变成了“用户-服务”“服务-服务”的多种场景。而且对于微服务架构而言,动辄就要面对数十个乃至上百个微服务之间的调用,那么该如何为这些调用提供高效安全的身份认证及鉴权呢?而且,当这些微服务面对外部用户请求时,如何提供细粒度的安全管控方案也是一个极为重要的问题。
为了解决微服务架构的安全问题,主要有如下四种解决方案:
- 单点登录(SSO)方案
- 分布式会话(Session)方案
- 客户端令牌(Token)方案
- 客户端令牌与API网关结合
需要注意的是,这几种解决方案彼此之间并不是毫无关系,反而是关联紧密层层递进,为开发者如何解决微服务架构下的安全问题提供了重要的指导作用。
单点登录(SSO)方案
简单来说,单点登录就是在多个系统中,用户只需一次登录,其他各个系统均可感知该用户已经登录。
一般的单点登录方案实现思路如下:
- 用户登录时,验证用户的账户和密码
- 生成一个Token保存在数据库中,将Token写到Cookie中
- 将用户数据保存在Session中
- 请求时都会带上Cookie,检查有没有登录,如果已经登录则放行
单点登录方案是最常见的解决方案,但需要每个与用户交互的服务都必须与认证服务进行通信,这不但会造成重复,也会产生大量琐碎的网络流量;
分布式会话(Session)方案
上面又说道,单点登录功能主要是用Session保存用户信息来实现的。但是多系统可能有多个Tomcat,而Session是依赖当前系统的Tomcat,所以系统A的Session和系统B的Session是不共享的。为了解决Session不共享问题,又产生了几种解决方案:
- Tomcat集群Session全局复制(集群内每个Tomcat的Session完全同步)
- 根据请求的IP进行Hash映射到对应的机器上(这就相当于请求的IP一直会访问同一个服务器)
- 把Session数据放在Redis中
前两种方案分别存在影响性能以及单系统故障数据丢失的问题,因此一般情况下会建议采用第三种方案,这也就是分布式会话方案。
通过将用户会话信息存储在共享存储(如Redis)中,并使用用户会话的ID作为key来实现分布式哈希映射。当用户访问微服务时,会话数据就可以从共享存储中获取。该解决方案在高可用和扩展方面都很好,但是由于会话信息保存在共享存储中,所以需要一定的保护机制保护数据安全,因此在具体的实现中会具有比较高的复杂度。
客户端令牌(Token)方案
令牌由客户端生成,并由认证服务器签名。在令牌中会包含足够的信息,客户端在请求时会将令牌附加在请求上,从而为各个微服务提供用户身份数据。此方案解决了分布式会话方案的安全性问题,但如何及时注销用户认证信息则是一个大问题,虽然可以使用短期令牌并频繁地与认证服务器进行校验,但并不可以彻底解决。JWT(JSON Web Tokens)是非常出名的客户端令牌解决方案,它足够简单,并且对各种环境支持程度也比较高。
客户端令牌与API网关结合
通过在微服务架构中实施API网关,可以将原始的客户端令牌转换为内部会话令牌。一方面可以有效地隐藏微服务,另一方面通过API网关的统一入口可以实现令牌的注销处理。
总结
随着近几年云服务应用的发展,基于令牌(Token)的认证使用范围也越来越广。对于基于令牌认证通常包含下面几层含义:
- 令牌是认证用户信息的集合,而不仅仅是一个无意义的ID;
- 在令牌中已经包含足够多的信息,验证令牌就可以完成用户身份的校验,从而减轻了因为用户验证需要检索数据库的压力,提升了系统性能;
- 因为令牌是需要服务器进行签名发放的,所以如果令牌通过解码认证,我们就可以认为该令牌所包含的信息是合法有效的;
- 服务器会通过HTTP头部中的Authorization获取令牌信息并进行检查,并不需要在服务器端存储任何信息;
- 通过服务器对令牌的检查机制,可以将基于令牌的认证使用在基于浏览器的客户端和移动设备的App或是第三方应用上;
- 可以支持跨程序调用。基于Cookie是不允许垮域访问的,而令牌则不存在这个问题
综上所述,基于令牌的认证由于会包含认证用户的相关信息,因此可以通过验证令牌来完成用户身份的校验,完全不同于之前基于会话的认证。因此,基于令牌的这个优点,像微信、支付宝、微博及GitHub等,都推出了基于令牌的认证服务,用于访问所开放的API及单点登录。
参考资料:
《Spring Cloud微服务架构开发实战》
https://zhuanlan.zhihu.com/p/66037342