抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

微服务授权方案对比

微服务授权方案对比

有状态 VS 无状态

​ 几乎绝大部分的应用都需要实现认证与授权,例如用户使用账户密码登录就是一个认证过程,认证登录成功后系统才会允许用户访问其账户下的相关资源,这就是所谓的授权。而复杂点的情况就是用户会有角色概念,每个角色所拥有的权限不同,给用户赋予某个角色的过程也是一个授权过程。

有状态模式

​ 用户的登录态在服务器端分为有状态和无状态两种模式,在单体分布式架构的时代,我们为了能让Session信息在多个Tomcat实例之间共享,通常的解决方案是将Session存储至一个缓存数据库中。即下图中的Session Store,这个Session Store可以是Redis也可以是MemCache,这种模式就是有状态的:

​ 之所以说是有状态,是因为服务端需要维护、存储这个Session信息,即用户的登录态实际是在服务端维护的,所以对服务端来说可以随时得知用户的登录态,并且对用户的Session有比较高的控制权。有状态模式的缺点主要是在于这个Session Store上,如果作为Session Store的服务只有一个节点的话,当业务扩展、用户量增多时就会有性能瓶颈问题,而且数据迁移也比较麻烦。当然也可以选择去增加节点,只不过就需要投入相应的机器成本了。

无状态模式

​ 另一种无状态模式,指的是服务器端不去记录用户的登录状态,也就是服务器端不再去维护一个Session。而是在用户登录成功的时候,颁发一个token给客户端,之后客户端的每个请求都需要携带token。服务端会对客户端请求时所携带的token进行解密,校验token是否合法以及是否已过期等等。token校验成功后则认为用户是具有登录态的,否则认为用户未登录:

注:token通常会存储用户的唯一ID,解密token就是为了获取用户ID然后去缓存或者数据库中查询用户数据。当然也可以选择将用户数据都保存在token中,只不过这种方式可能会有安全问题或数据一致性问题

​ 无状态模式下的token其实和有状态模式下的session作用是类似的,都是判断用户是否具有登录态的一个凭证。只不过在无状态模式下,服务器端不需要再去维护、存储一个Session,只需要对客户端携带的token进行解密和校验。也就是说存储实际是交给了客户端完成,所以无状态的优点恰恰就是弥补了有状态的缺点。但是无状态的缺点也很明显,因为一旦把token交给客户端后,服务端就无法去控制这个token了。例如想要强制下线某个用户在无状态的模式下就比较难以实现。

对比

有状态与无状态各有优缺点,只不过目前业界趋势更倾向于无状态:

优缺点 有状态 无状态
优点 服务端控制能力强 去中心化,无存储,简单,任意扩容、缩容
缺点 存在中心点,鸡蛋放在一个篮子里,迁移麻烦。服务端存储数据,加大了服务端压力 服务端控制能力相对弱

微服务认证方案对比

微服务认证方案有很多种,需要根据实际的业务需求定制适合自己业务的方案,这里简单列举一下业界内常用的微服务认证方案。

处处安全

​ 所谓“处处安全” 方案,就是考虑了微服务认证中的方方面面,这种方案主流是使用OAuth2协议进行实现。这种方案的优点是安全性好,但是实现的成本及复杂性比较高。另外,多个微服务之间互相调用需要传递token,所以会发生多次认证,有一定的性能开销

外部无状态,内部有状态

​ 这种方案虽然看着有些奇葩,但是也许多公司在使用。在该方案下,网关不存储Session,而是接收一个token和JSESSIONID,网关仅对token进行解密、校验,然后将JSESSIONID转发到其代理的微服务上,这些微服务则是通过JSESSIONID从Session Store获取共享Session。如下图:

​ 这种方案主要是出现在内部有旧的系统架构的情况,在不重构或者没法全部重构的前提下为了兼容旧的系统,就可以采用该方案。而且也可以将新旧系统分为两块,网关将token和JSESSIONID一并转发到下游服务,这样无状态模式的系统则使用token,有状态模式的系统则使用Session,然后再慢慢地将旧服务进行重构以此实现一个平滑过渡。如下图:

网关认证授权,内部裸奔

​ 在该方案下,认证授权在网关完成,下游的微服务不需要进行认证授权。网关接收到客户端请求所携带的token后,对该token进行解密和校验,然后将解密出来的用户信息转发给下游微服务。这种方案的优点是实现简单、性能也好,缺点是一旦网关被攻破,或者能越过网关访问微服务就会有安全问题。如下图:

内部裸奔改进版

​ 上一个方案的缺陷比较明显,我们可以对该方案进行一些改进,例如引入一个认证授权中心服务,让网关不再做认证和授权以及token的解密和解析。用户的登录请求通过网关转发到认证授权中心完成登录,登录成功后由认证授权中心颁发token给客户端。客户端每次请求都携带token,而每个微服务都需要对token进行解密和解析,以确定用户的登录态。改进之后所带来的好处就是网关不再关注业务,而是单纯的请求做转发,可以在一定程度上解耦业务,并且也更加安全,因为每个微服务不再裸奔而是都需要验证请求中所携带的token。如下图:

方案的对比与选择

​ 以上所提到的常见方案只是用于抛砖引玉,没有哪个方案是绝对普适的。而且实际开发中通常会根据业务改进、组合这些方案演变出不同的变种,所以应该要学会活学活用而不是局限于某一种方案。下面简单整理了一下这几种方案,以便做对比:

访问控制模型

​ 了解了常见的微服务认证方案后,我们来简单看下访问控制模型。所谓访问控制,就是用户需要满足怎么样的条件才允许访问某个系统资源,即控制系统资源的访问权限。访问控制模型主要有以下几种:

Access Control List(ACL,访问控制列表)

​ 在该模型下的一个系统资源会包含一组权限列表,该列表规定了哪些用户拥有哪些操作权限。例如有一个系统资源包含的权限列表为:[Alice: read, write; Bob: read];那么就表示Alice这个用户对该资源拥有read和write权限,而Bob这个用户则对该资源拥有read权限。该模型通常用于文件系统

Role-based access control(RBAC,基于角色的访问控制)

​ 即用户需关联一个预先定义的角色,而不同的角色拥有各自的权限列表。用户登录后只需要查询其关联的角色就能查出该用户拥有哪些权限。例如用户A关联了一个名为观察者的角色,该角色下包含接口A和接口B的访问权限,那么就表示用户A仅能够访问A和接口B。该模型在业务系统中使用得最多

Attribute-based access control(ABAC,基于属性的访问控制)

​ 在该模型下,用户在访问某个系统资源时会携带一组属性值包括自身属性、主题属性、资源属性以及环境属性等。然后系统通过动态计算用户所携带的属性来判断是否满足具有访问某个资源的权限。属性通常来说分为四类:用户属性(如用户年龄),环境属性(如当前时间),操作属性(如读取)以及对象属性等。

​ 为了能让系统进行权限控制,在该模型下需要以特定的格式定义权限规则,例如:IF 用户是管理员; THEN 允许对敏感数据进行读/写操作。在这条规则中“管理员”是用户的角色属性,而“读/写”是操作属性,”敏感数据“则是对象属性。

​ ABAC有时也被称为PBAC(Policy-Based Access Control,基于策略的访问控制)或CBAC(Claims-Based Access Control,基于声明的访问控制)。该模型由于比较复杂,使用得不多,k8s也因为ABAC太复杂而在1.8版本改为使用RBAC模型

Rules-based access control(RBAC,基于规则的访问控制)

​ 在该模型下通过对某个系统资源事先定义一组访问规则来实现访问控制,这些规则可以是参数、时间、用户信息等。例如:只允许从特定的IP地址访问或拒绝从特定的IP地址访问

Time-based access control list(TBACL,基于时间的访问控制列表)

​ 该模型是在ACL的基础上添加了时间的概念,可以设置ACL权限在特定的时间才生效。例如:只允许某个系统资源在工作日时间内才能被外部访问,那么就可以将该资源的ACL权限的有效时间设置为工作日时间内

评论