如何构建安全的微服务应用

本文转载于本人的微信公众号中的文章,最新文章请关注公众号。算法

目录
1、前言
2、单体应用认证和鉴权
3、微服务认证和鉴权
一、面临的问题
二、用户身份认证
三、用户状态保持
四、实现单点登陆
五、用户权限控制
六、微服务之间的认证与鉴权
七、第三方应用
4、总结后端

1、前言

咱们知道微服务技术或微服务架构是一把双刃剑,其给咱们带来了简单、灵活的部署,聚焦、专一快速迭代,低耦合、高内聚、易扩展等优点;与此同时,也引入了更加复杂的问题。本文要着重阐述的如何在微服务架构中实现一个安全、高效的认证和鉴权方案。浏览器

2、单体应用认证和鉴权

咱们先回想下,在单体应用架构时咱们是怎么对用户进行认证和鉴别权限的?在单体架构下,每每会采用一个安全模块来实现用户认证和鉴权。缓存

  • 用户认证
    当用户登陆时,应用内的安全模块对用户身份进行验证,验证用户身份合法后,为该用户生成一个会话(Session),并为该Session关联一个惟一的编号(Session Id)。Session是应用中的一小块内存结构,其中保存了登陆用户的信息,如User name, Role, Permission等。应用服务会将该Session的Session Id返回给客户端,客户端将Session Id以cookie或者URL重写的方式记录下来,并在后续请求中发送给应用,这样应用在接收到客户端访问请求时可使用Session Id验证用户身份,不用每次请求时都输入用户名和密码进行身份验证。安全

  • 用户鉴权
    在完成了用户认证后,应用服务对用户的每个请求携带过来的Session Id,进行对用户权限判断用户,以此判断用户是否能执行该此请求,以实现操做鉴权。服务器

3、微服务认证和鉴权

3.1 面临的问题

在微服务架构中,咱们知道微服务的粒度切分以业务边界为依据的。一个庞大的系统中,根据业务会划分出不少的微服务。对每个微服务的访问请求都须要进行认证和鉴权,微服务的认证和鉴权又面临哪些问题?微信

  1. 微服务架构下的认证和鉴权涉及到场景更为复杂,涉及到用户访问微服务应用,第三方应用访问微服务应用,微服务之间相互访问等多种场景,每种场景下的认证和鉴权方案都须要考虑到,如何来保证复杂场景下微服务的安全性?cookie

  2. 认证和鉴权逻辑,在微服务架构中放在什么位置、哪一层,更为合适?网络

  3. 认证和鉴权成功后的信息如何存储,如何维护调用方和服务方之间的认证关系?架构

  4. 微服务应用的权限粒度,如何作到API级别的控制?

3.2 技术方案

3.2.1 用户身份认证

在微服务体系架构中,微服务应用是由多个相互独立的微服务进程组成的,对每一个微服务的访问都须要进行用户认证。
微服务应用应遵循单一职责原理,即一个微服务只处理单一的业务逻辑。认证和鉴权的公共逻辑不该该放到微服务实现中。所以须要考虑一个抽象、公共的逻辑对用户进行身份认证和鉴权服务。因为在微服务架构中以API Gateway做为对外提供服务的入口,所以能够考虑在API Gateway处提供统一的用户认证。具体就技术实现采用Zuul+Spring Security+OAuth2/JWT。

3.2.2 用户状态保持

在单体应用时,咱们是在服务器端采用Session和客户端采用Cookie来保存用户状态,因为在服务器是有状态的,对服务器的水平扩展有影响。
咱们知道微服务架构的优点之一是微服务的水平扩展(Scalability)和弹性(Resiliency),因此微服务最好是无状态的。所以建议采用Token来记录用户登陆状态。
Token和Seesion主要的不一样点是存储的地方不一样。
Session是集中存储在服务器中的;而Token是用户本身持有的,通常以Cookie的形式存储在浏览器中。Token中保存了用户的身份信息,每次请求都会发送给Gateway,所以能够判断访问者的身份,并判断其对请求的资源有没有访问权限。
Token用于代表用户身份,其又以Cookie的形式存储在浏览器中。为了保障信息的安全,所以须要对其内容进行加密,避免被请求方或者第三者篡改。
JWT(Json Web Token)是一个定义Token格式的开放标准(RFC 7519),定义了Token的内容、加密方式并提供了各类语言的lib。
JWT Token的结构很是简单,包括三部分:

  • Header
    头部包含类型,为固定值JWT。而后是JWT使用的Hash算法。

{
  "alg": "HS256",
  "typ": "JWT"
}
  • Payload
    包含发布者,过时时间,用户名等标准信息,也能够添加用户角色,用户自定义的信息。

"sub": "1QAZWSX2", "name": "WY", "admin": true }
  • Signature
    Token颁发方的签名,用于客户端验证Token颁发方的身份,也用于服务器防止Token被篡改。 
    签名算法HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret),这三部分使用Base64编码后组合在一块儿,成为最终返回给客户端的Token,每部分之间采用”.“分隔。
    采用Token进行用户认证,服务器端再也不保存用户状态,客户端每次请求时都须要将Token发送到服务器端进行身份验证。
    Token发送的方式rfc6750进行了规定,采用一个 Authorization: Bearer HHTP Header进行发送。

Authorization: Bearer 37mF-90B5f-86JqM

采用Token方式进行用户认证的基本流程以下图所示:

  1. 用户输入用户名,密码等验证信息,向服务器发起登陆请求

  2. 服务器端验证用户登陆信息,生成JWT token

  3. 服务器端将Token返回给客户端,客户端保存在本地(通常以Cookie的方式保存)

  4. 客户端向服务器端发送访问请求,请求中携带以前颁发的Token

  5. 服务器端验证Token,确认用户的身份和对资源的访问权限,并进行相应的处理(拒绝或者容许访问)

  • 关于Token注销
    因为Token不存储在服务端,由客户端存储。当用户注销时,Token的有效时间尚未到,仍是有效的。因此如何在用户注销登陆时让Token注销是一个要关注的点。通常有以下几种方式:

  1. Token存储在Cookie中,这样客户端注销时,天然能够清空掉

  2. 将Token存放到分布式缓存中,每次校验Token时区检查下该Token是否已注销。不过这样也就失去了快速校验Token的优势。

  3. 多采用短时间令牌,好比令牌有效期是30分钟,这样能够必定程度上下降注销后 Token可用性的风险。

3.2.3 单点登陆

咱们看下维基百科中,对单点登陆的解释。

单点登陆(英语:Single sign-on,缩写为 SSO),又译为单一签入,一种对于许多相互关连,可是又是各自独立的软件系统,提供访问控制的属性。当拥有这项属性时,当用户登陆时,就能够获取全部系统的访问权限,不用对每一个单一系统都逐一登陆。相同的,单一注销(single sign-off)就是指,只须要单一的注销动做,就能够结束对于多个系统的访问权限。

在微服务架构中,单点登陆能够理解为当用户登陆成功后,就能够访问全部有权限访问的微服务。API Gateway提供了客户端访问微服务的入口,Token实现了无状态的用户认证。结合这两种技术,咱们就能够为微服务应用实现一个单点登陆方案。

微服务单点登陆流程下,用户的认证和鉴权以下图:

  • 用户登陆

  1. 客户端发送登陆请求到API Gateway

  2. API Gateway将登陆请求转发到Security Service

  3. Security Service验证用户身份,并颁发Token

  • 用户请求

  1. 客户端请求发送到API Gateway

  2. API Gateway调用的Security Service对请求中的Token进行验证,检查用户的身份

  3. 若是请求中没有Token,Token过时或者Token验证非法,则拒绝用户请求。

  4. Security Service检查用户是否具备该操做权

  5. 若是用户具备该操做权限,则把请求发送到后端的Business Service,不然拒绝用户请求。

3.2.4 用户权限控制

API Gateway处进行统一的权限控制
客户端发送的HTTP请求中包含有请求的Resource及HTTP Method。若是系统遵循REST规范,以URI资源方式对访问对象进行建模,则API Gateway能够从请求中直接截取到访问的资源及须要进行的操做,而后调用Security Service进行权限判断,根据判断结果决定用户是否有权限对该资源进行操做,并转发到后端的Business Service。这种实现方式API Gateway处统一处理认证和鉴权逻辑,各个微服务不须要考虑用户认证和鉴权,只须要处理业务逻辑,简化了各微服务的实现。

3.2.5 微服务之间的认证

微服务应用,除了来自用户和第三方的访问外,还有大量的微服务之间访问。根据微服务应用的数据敏感程度的不一样,对于微服务之间的相互访问可能有不一样的安全要求

  • 微服务间的相互访问不进行认证和鉴权

  1. 依托网络安全措施,来保障微服务间的通信安全

  2. 微服务提供的数据敏感程度不是很高
    在这种状况下,一旦攻击者侵入到内部网络后没有了保护措施。虽然微服务的数据敏感程度不高,可是攻击行为仍然给咱们带来危害。

  • 服务间的访问采用颁发访问凭证进行安全控制
    微服务在使用的纬度上,咱们定义服务的调用方和服务的提供方。服务的提供方对调用方颁发访问凭证,提供方对访问严格控制;没有访问凭证的访问,拒绝访问;根据不一样的访问凭证类型,安全控制不一样的访问类型。

  • 服务间的访问采用Service Account进行安全控制
    Istio-Auth提供强大的服务间认证和终端用户认证,使用交互TLS,内置身份和证书管理。能够升级服务网格中的未加密流量,并为运维人员提供基于服务身份而不是网络控制来执行策略的能力。Istio的将来版本将增长细粒度的访问控制和审计,以使用各类访问控制机制(包括基于属性和角色的访问控制以及受权钩子)来控制和监视访问您的服务,API或资源的人员。

Istio Security Architecture

Istio-Auth更多信息:https://istio.io/docs/concepts/security/mutual-tls/

3.2.6 第三方应用

OAuth2
OAuth2针对不一样场景有不一样的认证流程,一个典型的认证流程以下图所示:

(图片来源于网络)

  1. 用户向OAuth客户端程序发起一个请求,OAuth客户端程序在处理该请求时发现须要访问用户在资源服务器中的数据。

  2. 客户端程序将用户请求重定向到认证服务器,该请求中包含一个callback的URL。

  3. 认证服务器返回受权页面,要求用户对OAuth客户端的资源请求进行受权。

  4. 用户对该操做进行受权后,认证服务器将请求重定向到客户端程序的callback url,将受权码返回给客户端程序。

  5. 客户端程序将受权码发送给认证服务器,请求token。

  6. 认证服务器验证受权码后将token颁发给客户端程序。

  7. 客户端程序采用颁发的token访问资源,完成用户请求。

POST /oauth/token HTTP/1.1
Host: authorization-server.com

grant_type=authorization_code
&code=xxxxxxxxxxx
&redirect_uri=https://example-app.com/redirect
&client_id=xxxxxxxxxx
&client_secret=xxxxxxxxxx

(引用:https://www.oauth.com/oauth2-servers/access-tokens/authorization-code-request/)

4、总结

微服务架构下,认证和鉴权涉及到场景复杂,涉及到用户访问微服务应用,第三方应用访问微服务应用,微服务之间相互访问等多种场景。

  • 身份认证。确认“你是你”,获取你的身份信息。

  • 权限验证。确认“你能作某件事”。

权限建模时,每每会拆分红功能权限和数据权限。上述的解决方案,从功能权限结合各类微服务应用场景下,抽象了身份认证和权限验证模型。

-EOF-

相关文章
相关标签/搜索