微服务架构认证方案

单体应用

单体应用体系下,应用是一个整体,一般针对所有的请求都会进行权限校验。请求一般会通过一个权限的拦截器进行权限的校验,在登录时将用户信息缓存到 session 中,后续访问则从缓存中获取用户信息。

d1e19fda.png

微服务

要考虑外部应用接入的场景、用户 - 服务的鉴权、服务 - 服务的鉴权等多种鉴权场景。
e5ce1cb1.png

David Borsos 在伦敦的微服务大会上提出了四种方案

单点登录(SSO)

这种方案意味着每个面向用户的服务都必须与认证服务交互,这会产生大量非常琐碎的网络流量和重复的工作,当动辄数十个微应用时,这种方案的弊端会更加明显。

分布式 Session 方案

分布式会话方案原理主要是将关于用户认证的信息存储在共享存储中,且通常由用户会话作为 key 来实现的简单分布式哈希映射。当用户访问微服务时,用户数据可以从共享存储中获取。在某些场景下,这种方案很不错,用户登录状态是不透明的。同时也是一个高可用且可扩展的解决方案。这种方案的缺点在于共享存储需要一定保护机制,因此需要通过安全链接来访问,这时解决方案的实现就通常具有相当高的复杂性了。

客户端 Token 方案

令牌在客户端生成,由身份验证服务进行签名,并且必须包含足够的信息,以便可以在所有微服务中建立用户身份。令牌会附加到每个请求上,为微服务提供用户身份验证,这种解决方案的安全性相对较好,但身份验证注销是一个大问题,缓解这种情况的方法可以使用短期令牌和频繁检查认证服务等。对于客户端令牌的编码方案,Borsos 更喜欢使用 JSON Web Tokens(JWT),它足够简单且库支持程度也比较好。
289f8fb0.png

基于Token的两个解决方案:

  1. JWT
  2. Oauth2.0。
    OAuth 2.0 的流程如下:33d6d487.png

(A)用户打开客户端以后,客户端要求用户给予授权。
(B)用户同意给予客户端授权。
(C)客户端使用上一步获得的授权,向认证服务器申请令牌。
(D)认证服务器对客户端进行认证以后,确认无误,同意发放令牌。
(E)客户端使用令牌,向资源服务器申请获取资源。
(F)资源服务器确认令牌无误,同意向客户端开放资源。

OAuth 2.0 有四个角色:客户端、资源拥有者、资源服务器、授权服务器。
客户端:客户端是代表资源所有者对资源服务器发出访问受保护资源请求的应用程序。
资源拥有者:资源拥有者是对资源具有授权能力的人。
资源服务器:资源所在的服务器。
授权服务器:为客户端应用程序提供不同的 Token,可以和资源服务器在统一服务器上,也可以独立出去。

客户端的授权模式

客户端必须得到用户的授权(Authorization Grant),才能获得令牌(access token)。
OAuth 2.0 定义了四种授权方式:authorizationcode,implicit,resource owner password credentials,client credentials。

  1. 授权码模式(authorization code)

授权码模式(authorization code)是功能最完整、流程最严密的授权模式。它的特点就是通过客户端的后台服务器,与”服务提供商”的认证服务器进行互动。
流程如下:
用户访问客户端,后者将前者导向认证服务器。
用户选择是否给予客户端授权。
假设用户给予授权,认证服务器将用户导向客户端事先指定的”重定向 URI”(redirection URI),同时附上一个授权码。
客户端收到授权码,附上早先的”重定向 URI”,向认证服务器申请令牌。这一步是在客户端的后台的服务器上完成的,对用户不可见。
认证服务器核对了授权码和重定向 URI,确认无误后,向客户端发送访问令牌(access token)和更新令牌(refresh token)。

  1. 简化模式(implicit)

简化模式(Implicit Grant Type)不通过第三方应用程序的服务器,直接在浏览器中向认证服务器申请令牌,跳过了”授权码”这个步骤,因此得名。所有步骤在浏览器中完成,令牌对访问者是可见的,且客户端不需要认证。
流程如下:
客户端将用户导向认证服务器。
用户决定是否给于客户端授权。
假设用户给予授权,认证服务器将用户导向客户端指定的”重定向 URI”,并在 URI 的 Hash 部分包含了访问令牌。
浏览器向资源服务器发出请求,其中不包括上一步收到的 Hash 值。
资源服务器返回一个网页,其中包含的代码可以获取 Hash 值中的令牌。
浏览器执行上一步获得的脚本,提取出令牌。
浏览器将令牌发给客户端。

  1. 密码模式(Resource Owner Password Credentials)

密码模式中,用户向客户端提供自己的用户名和密码。客户端使用这些信息,向”服务商提供商”索要授权。在这种模式中,用户必须把自己的密码给客户端,但是客户端不得储存密码。这通常用在用户对客户端高度信任的情况下,比如客户端是操作系统的一部分,或者由一个著名公司出品。而认证服务器只有在其他授权模式无法执行的情况下,才能考虑使用这种模式。

流程如下:
用户向客户端提供用户名和密码。
客户端将用户名和密码发给认证服务器,向后者请求令牌。
认证服务器确认无误后,向客户端提供访问令牌。

  1. 客户端模式(Client Credentials)

客户端模式(Client Credentials Grant)指客户端以自己的名义,而不是以用户的名义,向”服务提供商”进行认证。
严格地说,客户端模式并不属于 OAuth 框架所要解决的问题。
在这种模式中,用户直接向客户端注册,客户端以自己的名义要求”服务提供商”提供服务,其实不存在授权问题。流程如下:
客户端向认证服务器进行身份认证,并要求一个访问令牌。
认证服务器确认无误后,向客户端提供访问令牌。

客户端 Token 与 API 网关结合

这个方案意味着所有请求都通过网关,从而有效地隐藏了微服务。 在请求时,网关将原始用户令牌转换为内部会话 ID 令牌。在这种情况下,注销就不是问题,因为网关可以在注销时撤销用户的令牌。