如何在微服务架构中实现安全性?

本文涉及的产品
云原生网关 MSE Higress,422元/月
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
注册配置 MSE Nacos/ZooKeeper,118元/月
简介: 网络安全已成为每个企业都面临的关键问题。几乎每天都有关于黑客如何窃取公司数据的头条新闻。为了开发安全的软件并远离头条新闻,企业需要解决各种安全问题,包括硬件的物理安全性、传输和静态数据加密、身份验证、访问授权以及修补软件漏洞的策略,等等。

image.png

作者 | Chris Richardson

网络安全已成为每个企业都面临的关键问题。几乎每天都有关于黑客如何窃取公司数据的头条新闻。为了开发安全的软件并远离头条新闻,企业需要解决各种安全问题,包括硬件的物理安全性、传输和静态数据加密、身份验证、访问授权以及修补软件漏洞的策略,等等。无论你使用的是单体还是微服务架构,大多数问题都是相同的。本文重点介绍微服务架构如何影响应用程序级别的安全性。
应用程序开发人员主要负责实现安全性的四个不同方面:

1.身份验证:验证尝试访问应用程序的应用程序或人员(安全的术语叫主体)的身份。例如,应用程序通常会验证访问的凭据,例如用户的 ID 和密码,或应用程序的 API 密钥。

2.访问授权:验证是否允许访问主体对指定数据完成请求的操作。应用程序通常使用基于角色的安全性和访问控制列表(ACL)的组合。基于角色的安全性为每个用户分配一个或多个角色,授予他们调用特定操作的权限。ACL 授予用户或角色对特定业务对象或聚合执行操作的权限。

3.审计:跟踪用户在应用中执行的所有操作,以便检测安全问题,帮助客户实现并强制执行合规性。

4.安全的进程间通信:理想情况下,所有进出服务的通信都应该采用传输层安全性(TLS)加密。服务间通信甚至可能需要使用身份验证。

下面将重点介绍如何实现身份验证和访问授权。审计和安全的进程间通信的更多详细介绍请参阅 Chris Richardson 的《微服务架构设计模式》。

我首先描述如何在 FTGO 单体应用程序中实现安全性。然后介绍在微服务架构中实现安全性所面临的挑战,以及为何在单体架构中运行良好的技术不能在微服务架构中使用。之后,我将介绍如何在微服务架构中实现安全性。

让我们首先回顾一下 FTGO 单体应用程序如何处理安全性。

传统单体应用程序的安全性

FTGO 应用程序有多种用户,包括消费者、送餐员和餐馆员工。他们使用基于浏览器的 Web 应用程序和移动应用程序访问 FTGO。所有 FTGO 用户都必须登录才能访问该应用程序。图 1 显示了单体 FTGO 应用程序的客户端如何验证和发出请求。

image.png

图 1 FTGO 应用程序的客户首先登录以获取会话令牌,该令牌通常是 cookie。客户在向 FTGO 应用程序发出的每个后续请求中都会包括会话令牌

当用户使用其用户 ID 和密码登录时,客户端会向 FTGO 应用程序发出包含用户凭据的 POST 请求。FTGO 应用程序验证凭据并将会话令牌返回给客户端。客户端在 FTGO 应用程序的每个后续请求中包含会话令牌。

图 2 显示了 FTGO 应用程序如何实现安全性。FTGO 应用程序是用 Java 编写的,并使用 Spring Security 框架,但我将使用同样也适用于其他框架(例如 Passport for Node.js)的一般性术语来描述这个设计。

image.png

图 2 当 FTGO 应用程序的客户端发出登录请求时,登录处理程序会对用户进行身份验证,初始化会话用户信息,并返回会话令牌 cookie,以便安全地识别会话。接下来,当客户端发出包含会话令牌的请求时,SessionBasedSecurityInterceptor 从指定的会话中检索用户信息并建立安全上下文。请求处理程序(如 OrderDetailsRequestHandler)从安全上下文中检索用户信息

使用安全框架

正确实现身份验证和访问授权具有挑战性。最好使用经过验证的安全框架。使用哪个框架取决于你的应用程序的技术栈。流行的框架包括以下几个:

SpringSecurity:适用于 Java 应用程序的流行框架。它是一个复杂的框架,可以处理身份验证和访问授权。

ApacheShiro:另一个 Java 安全框架。

Passport:在 Node.js 应用程序流行的一个专注于身份验证的安全框架。

安全架构的一个关键部分是会话,它存储主体的 ID 和角色。FTGO 应用程序是传统的 Java EE 应用程序,因此会话是 HttpSession 内存中会话。会话令牌代表着每一个具体的会话,客户端在每个请求中包含会话令牌。它通常是一串无法读懂的数字标记,例如经过加密的强随机数。FTGO 应用程序的会话令牌是一个名为 JSESSIONID 的 HTTP cookie。

实现安全性的另一个关键是安全上下文,它存储有关发出当前请求的用户的信息。Spring Security 框架使用标准的 Java EE 方法将安全上下文存储在静态的线程局部变量中,任何被调用以处理请求的代码都可以访问该变量。请求处理程序可以调用 SecurityContextHolder. getContext().getAuthentication() 获取有关当前用户的信息,例如他们的身份和角色。相反,Passport 框架将安全上下文存储为 request 对象的 user 属性。

图 2 中显示的事件序列如下:

1.客户端向 FTGO 应用程序发出登录请求。

2.登录请求由 LoginHandler 处理,LoginHandler 验证凭据,创建会话,并在会话中存储有关主体的信息。

3.Login Handler 将会话令牌返回给客户端。

4.客户端在后续每次调用请求中都包含会话令牌。

5.这些请求首先由 SessionBasedSecurityInterceptor 处理。拦截器通过验证会话令牌来验证每个请求并建立安全上下文。安全上下文描述了主体及其角色。

6.请求处理程序使用安全上下文来获取其身份,并借此确定是否允许用户执行请求的操作。

FTGO 应用程序使用基于角色的授权。它定义了与不同类型用户相对应的几个角色,包括 CONSUMER、RESTAURANT、COURIER 和 ADMIN。它使用 Spring Security 的声明性安全机制来限制对特定角色的 URL 和服务方法的访问。角色也与业务逻辑交织在一起。例如,消费者只能访问自己的订单,而管理员可以访问所有订单。

单体 FTGO 应用程序使用的安全设计只是实现安全性的一种可能方式。例如,使用内存中会话的一个缺点是,它必须把特定会话的所有请求路由到同一个应用程序实例。这个要求使负载均衡和操作变复杂了。例如,你必须实现会话耗尽机制,该机制在关闭应用程序实例之前等待所有会话到期(以免丢失内存中已有的会话)。避免这些问题的另一种方法是将会话存储在数据库中。

开发者可以完全不保存服务器端会话。例如,许多应用程序都有 API 客户端,可以在每个请求中提供其凭据,例如 API 密钥和私钥。因此,无须维护服务器端会话。或者,应用程序可以将会话状态存储在会话令牌中。在本文的后面,我将介绍一种使用会话令牌存储会话状态的方法。但让我们首先看一下在微服务架构中实现安全性的挑战。

在微服务架构中实现安全性

微服务架构是分布式架构。每个外部请求都由 API Gateway 和至少一个服务处理。例如,考虑 getOrderDetails() 查询。API Gateway 通过调用多个服务来处理此查询,包括 Order Service、Kitchen Service 和 Accounting Service。每项服务都必须实现安全性的某些方面。例如,Order Service 必须只允许消费者查看他们自己的订单,这需要结合身份验证和访问授权。为了在微服务架构中实现安全性,我们需要确定谁负责验证用户身份以及谁负责访问授权。

在微服务应用程序中实现安全性的一个挑战是我们不能仅仅从单体应用程序借鉴设计思路。这是因为单体应用程序的安全架构的一些方面对微服务架构来说是不可用的,例如:

1.内存中的安全上下文:使用内存中的安全上下文(如 ThreadLocal)来传递用户身份。服务无法共享内存,因此它们无法使用内存中的安全上下文(如 ThreadLocal)来传递用户身份。在微服务架构中,我们需要一种不同的机制来将用户身份从一个服务传递到另一个服务。

2.集中会话:因为内存中的安全上下文没有意义,内存会话也没有意义。从理论上讲,多种服务可以访问基于数据库的会话,但它会违反松耦合的原则。我们需要在微服务架构中使用不同的会话机制。

让我们通过研究如何处理身份验证来开始探索微服务架构中的安全性。

由 API Gateway 处理身份验证

处理身份验证有两种不同的方法。一种选择是让各个服务分别对用户进行身份验证。这种方法的问题在于它允许未经身份验证的请求进入内部网络。它依赖于每个开发团队在所有服务中正确实现安全性。因此,出现安全漏洞的风险和概率都很大。

在服务中实现身份验证的另一个问题是不同的客户端以不同的方式进行身份验证。纯 API 客户端使用基本身份验证为每个请求提供凭据。其他客户端可能首先登录,然后为每个请求提供会话令牌。但我们要避免在服务中处理多种不同的身份验证机制。

更好的方法是让 API Gateway 在将请求转发给服务之前对其进行身份验证。在 API Gateway 中进行集中 API 身份验证的优势在于只需要确保这里的验证是正确的。因此,出现安全漏洞的可能性要小得多。另一个好处是只有 API Gateway 需要处理各种不同的身份验证机制。这使得其他服务的实现变得简单了。

图 3 显示了这种方法的工作原理。客户端使用 API Gateway 进行身份验证。API 客户端在每个请求中包含凭据。基于登录的客户端将用户的凭据发送到 API Gateway 进行身份验证,并接收会话令牌。一旦 API Gateway 验证了请求,它就会调用一个或多个服务。

image.png

图 3 API Gateway 对来自客户端的请求进行身份验证,并在其对服务的请求中包含安全令牌。服务使用令牌获取有关主体的信息。API Gateway 还可以将安全令牌用作会话令牌

模式:访问令牌

API Gateway 将包含用户信息(例如其身份和角色)的令牌传递给它调用的服务。请参阅:

http://microservices.io/patterns/security/access-token.html

API Gateway 调用的服务需要知道发出请求的主体(用户的身份)。它还必须验证请求是否已经过通过身份验证。解决方案是让 API Gateway 在每个服务请求中包含一个令牌。服务使用令牌验证请求,并获取有关主体的信息。API Gateway 还可以为面向会话的客户端提供相同的令牌,以用作会话令牌。

客户端的事件序列如下:

客户端发出包含凭据的请求给 API Gateway。

API Gateway 对凭据进行身份验证,创建安全令牌,并将其传递给服务。

基于登录的客户端的事件序列如下:

客户端发出包含凭据的登录请求。

API Gateway 返回安全令牌。

客户端在调用操作的请求中包含安全令牌。

API Gateway 验证安全令牌并将其转发给服务。

让我们首先看一下安全性的另一个主要方面:访问授权。

处理访问授权

验证客户端的凭据很重要,但这还不够。应用程序还必须实现访问授权机制,以验证是否允许客户端执行所请求的操作。例如,在 FTGO 应用程序中,getOrderDetails() 查询只能由下此 Order 的消费者(基于实例的安全性的一个示例)和为所有消费者提供服务的客户服务代表调用。

实现访问授权的一个位置是 API Gateway。例如,它可以将对 GET/orders/{orderId}的访问限制为消费者和客户服务代表。如果不允许用户访问特定路径,则 API Gateway 可以在将请求转发到服务之前拒绝该请求。与身份验证一样,在 API Gateway 中集中实现访问授权可降低安全漏洞的风险。你可以使用安全框架(如 Spring Security)在 API Gateway 中实现访问授权。

在 API Gateway 中实现访问授权的一个弊端是,它有可能产生 API Gateway 与服务之间的耦合,要求它们以同步的方式进行代码更新。而且,API Gateway 通常只能实现对 URL 路径的基于角色的访问。由 API Gateway 实现对单个领域对象的访问授权通常是不实际的,因为这需要详细了解服务的领域逻辑。

另一个实现访问授权的位置是服务。服务可以对 URL 和服务方法实现基于角色的访问授权。它还可以实现 ACL 来管理对聚合的访问。例如,在 Order Service 中可以实现基于角色和基于 ACL 的授权机制,以控制对 Order 的访问。FTGO 应用程序中的其他服务也可以实现类似的访问授权逻辑。

使用 JWT 传递用户身份和角色

在微服务架构中实现安全性时,你需要确定 API Gateway 应使用哪种类型的令牌来将用户信息传递给服务。有两种类型的令牌可供选择。一种选择是使用不透明(无可读性)的令牌,它们通常是一串 UUID。不透明令牌的缺点是它们会降低性能和可用性,并增加延迟。因为这种令牌的接收方必须对安全服务发起同步 RPC 调用,以验证令牌并检索用户信息。

另一种消除对安全服务调用的方法是使用包含有关用户信息的透明令牌。透明令牌的一个流行的标准是 JSON Web 令牌(JWT)。JWT 是在访问双方之间安全地传递信息(例如用户身份和角色)的标准方式。JWT 的内容包含一个 JSON 对象,其中有用户的信息,例如其身份和角色,以及其他元数据,如到期日期等。它使用仅为 JWT 的创建者所知的数字签名,例如 API Gateway 和 JWT 的接收者(服务)。该签名确保恶意第三方不能伪造或篡改 JWT。

因为不需要再访问安全服务进行验证,JWT 的一个问题是这个令牌是自包含的,也就是说它是不可撤消的。根据设计,服务将在验证 JWT 的签名和到期日期之后执行请求操作。因此,没有切实可行的方法来撤消落入恶意第三方手中的某个 JWT 令牌。解决方案是发布具有较短到期时间的 JWT,这可以限制恶意方。但是,短期 JWT 的一个缺点是应用程序必须以某种方式不断重新发布 JWT 以保持会话活动。幸运的是,这是 OAuth 2.0 安全标准旨在解决的众多问题之一。让我们来看看它是如何工作的。

在微服务架构中使用 OAuth 2.0

假设你要为 FTGO 应用程序实现一个 User Service,该应用程序管理包含用户信息(如凭据和角色)的数据库。API Gateway 调用 User Service 来验证客户端请求并获取 JWT。你可以设计 User Service 的 API 并使用你喜欢的 Web 框架实现它。但这不是 FTGO 应用程序特有的通用功能,自己开发此类服务往往是得不偿失的。

幸运的是,你不需要开发这种安全基础设施。你可以使用名为 OAuth 2.0 的标准的现成服务或框架。OAuth 2.0 是一种访问授权协议,最初旨在使公共云服务(如 GitHub 或 Google)的用户能够授予第三方应用程序访问其信息的权限,而不必向第三方应用透露他们的密码。例如,OAuth 2.0 使你能够安全地授予第三方基于云的持续集成(CI)服务,访问你的 GitHub 存储库。

虽然 OAuth 2.0 最初的重点是授权访问公共云服务,但你也可以将其用于应用程序中的身份验证和访问授权。让我们快速了解一下微服务架构如何使用 OAuth 2.0。

OAuth 2.0 中的关键概念如下:

授权服务器:提供用于验证用户身份以及获取访问令牌和刷新令牌的 API。Spring OAuth 是一个很好的用来构建 OAuth 2.0 授权服务器的框架。

访问令牌:授予对资源服务器的访问权限的令牌。访问令牌的格式取决于具体的实现技术。Spring OAuth 的实现中采用了 JWT 格式的访问令牌。

刷新令牌:客户端用于获取新的 AccessToken 的长效但同时也可被可撤消的令牌。

资源服务器:使用访问令牌授权访问的服务。在微服务架构中,服务是资源服务器。

客户端:想要访问资源服务器的客户端。在微服务架构中,API Gateway 是 OAuth 2.0 客户端。

首先,我们来谈谈如何验证 API 客户端,然后介绍如何支持基于登录的客户端。

图 4 显示了 API Gateway 如何验证来自 API 客户端的请求。API Gateway 通过向 OAuth 2.0 授权服务器发出请求来验证 API 客户端,该服务器返回访问令牌。然后,API Gateway 将包含访问令牌的一个或多个请求发送到服务。

image.png

图 4 API Gateway 通过向 OAuth 2.0 身份验证服务器发出请求来验证 API 客户端。身份验证服务器返回访问令牌,API Gateway 将其传递给服务。服务验证令牌的签名,并提取有关用户的信息,包括其身份和角色

图 4 所示的事件顺序如下:

1.客户端发出请求,使用基本身份验证提供它的凭据。

2.API Gateway 向 OAuth 2.0 身份验证服务器发出 OAuth 2.0 密码授予(Password Grant)请求(www.oauth.com/oauth2-servers/access-tokens/password-grant/)。

3.身份验证服务器验证 API 客户端的凭据,并返回访问令牌和刷新令牌。

4.API Gateway 在其对服务的请求中包含访问令牌。服务验证访问令牌并使用它来授权请求。

基于 OAuth 2.0 的 API Gateway 可以使用 OAuth 2.0 访问令牌作为会话令牌来验证面向会话的客户端。而且,当访问令牌到期时,它可以使用刷新令牌获得新的访问令牌。图 5 显示了 API Gateway 如何使用 OAuth 2.0 来处理面向会话的客户端。API 客户端通过将其凭据(发送 POST)到 API Gateway 的 /login 端点来启动会话。API Gateway 向客户端返回访问令牌和刷新令牌。然后,API 客户端在向 API Gateway 发出请求时提供这两个令牌。

image.png

图 5 客户端通过将其凭据发送到 API Gateway 来登录。API Gateway 使用 OAuth 2.0 身份验证服务器对凭据进行身份验证,并将访问令牌和刷新令牌作为 cookie 返回。客户端在其对 API Gateway 的请求中包括这些令牌

事件顺序如下:

基于登录的客户端将其凭据发送到 API Gateway。

API Gateway 的 LoginHandler 向 OAuth 2.0 身份验证服务器发出密码授予请求(www. oauth.com/oauth2-servers/access-tokens/password-grant/)。

身份验证服务器验证客户端的凭据,并返回访问令牌和刷新令牌。

API Gateway 将访问令牌和刷新令牌返回给客户端,通常是采用 cookie 的形式。

客户端在向 API Gateway 发出的请求中包含访问令牌和刷新令牌。

API Gateway 的 Session Authentication Interceptor 验证访问令牌,并将其包含在对服务的请求中。

如果访问令牌已经过期或即将过期,API Gateway 将通过发出 OAuth 2.0 刷新授权请求来获取新的访问令牌(www.oauth.com/oauth2-servers/access-tokens/refresh-access-tokens/),刷新授权请求发送给授权服务器,请求中包含刷新令牌。如果刷新令牌尚未过期或未被撤消,则授权服务器将返回新的访问令牌。API Gateway 将新的访问令牌传递给服务并将其返回给客户端。

使用 OAuth 2.0 的一个重要好处是它是经过验证的安全标准。使用现成的 OAuth 2.0 身份验证服务器意味着你不必浪费时间重新发明轮子或者是没有开发不安全的设计的风险。但 OAuth 2.0 不是在微服务架构中实现安全性的唯一方法。无论你使用哪种方法,三个关键思想如下:

1.API Gateway 负责验证客户端的身份。

2.API Gateway 和服务使用透明令牌(如 JWT)来传递有关主体的信息。

3.服务使用令牌获取主体的身份和角色。

本文摘自《微服务架构设计模式》,经出版方授权发布。

文章来源:微信公众号 IT牧场

目录
相关文章
|
19天前
|
运维 Kubernetes Cloud Native
云原生技术浪潮下的微服务架构演进
在数字化转型的风潮中,云原生技术以其灵活性、可扩展性和弹性成为企业IT战略的核心。本文深入探讨了微服务架构如何借助云原生环境进行优化,并分析了容器化、服务网格等技术如何助力微服务更好地适应云原生生态。通过案例分析,我们揭示了微服务在现代云平台上的实践挑战与解决策略,同时对未来的技术趋势进行了预测。
36 0
|
2天前
|
监控 负载均衡 API
从单体到微服务:架构转型之道
【8月更文挑战第17天】从单体架构到微服务架构的转型是一项复杂而系统的工程,需要综合考虑技术、团队、文化等多个方面的因素。通过合理的规划和实施策略,可以克服转型过程中的挑战,实现系统架构的升级和优化。微服务架构以其高度的模块化、可扩展性和灵活性,为业务的持续发展和创新提供了坚实的技术保障。
|
11天前
|
Cloud Native 云计算 微服务
云原生时代:企业分布式应用架构的惊人蜕变,从SOA到微服务的大逃亡!
【8月更文挑战第8天】在云计算与容器技术推动下,企业分布式应用架构正经历从SOA到微服务再到云原生的深刻变革。SOA强调服务重用与组合,通过标准化接口实现服务解耦;微服务以细粒度划分服务,增强系统灵活性;云原生架构借助容器化与自动化技术简化部署与管理。每一步演进都为企业带来新的技术挑战与机遇。
38 6
|
9天前
|
设计模式 监控 API
探索微服务架构中的API网关模式
在微服务的宇宙里,API网关是连接星辰的桥梁。它不仅管理着服务间的通信流量,还肩负着保护、增强和监控微服务集群的重任。本文将带你走进API网关的世界,了解其如何成为微服务架构中不可或缺的一环,以及它在实际应用中扮演的角色和面临的挑战。
|
12天前
|
缓存 监控 API
【微服务战场上的神秘守门人】:揭秘API网关的超能力 —— 探索微服务架构中的终极守护者与它的神奇魔法!
【8月更文挑战第7天】随着微服务架构的流行,企业应用被拆分为围绕特定业务功能构建的小型服务。API网关作为微服务间的通信管理核心,对请求进行路由、认证、限流等处理,简化客户端集成并提升用户体验。以电商应用为例,通过Kong部署API网关,配置产品目录等服务的API及JWT认证插件,确保安全高效的数据交互。这种方式不仅增强了系统的可维护性和扩展性,还提供了额外的安全保障。
29 2
|
17天前
|
运维 监控 负载均衡
探索微服务架构中的API网关
在现代软件开发中,微服务架构已成为设计灵活、可扩展系统的首选方法。本文将深入探讨API网关的核心作用,包括它如何简化客户端与微服务之间的交互,提供请求路由、负载均衡、认证、限流及监控等关键功能。我们将通过实际案例分析,揭示API网关在提升系统性能、增强安全性和提高开发效率方面的重要性。
|
15天前
|
负载均衡 监控 API
探索微服务架构中的API网关模式
在微服务架构的海洋中,API网关扮演着枢纽的角色。它不仅是客户端请求的接收者,也是各个微服务间通信的协调者。本文将深入探讨API网关的设计原则、实现策略以及它在微服务生态中的重要性。我们将通过实际案例分析,了解API网关如何优化系统性能、提高安全性和简化客户端与服务的交互。
31 4
|
15天前
|
运维 监控 负载均衡
探索微服务架构中的API网关设计
在微服务架构的复杂性中,API网关作为客户端和后端服务间的桥梁,扮演着至关重要的角色。本文将深入探讨如何设计一个高效、可扩展且安全的API网关,包括处理请求转发、负载均衡、身份验证、监控与日志记录等核心功能,并讨论如何在保障性能的同时确保系统的高可用性和安全性。通过具体案例,我们将了解API网关在实际生产环境中的实现方式及其对整个微服务生态系统的影响。
37 3
|
15天前
|
Kubernetes 监控 开发者
探索后端开发的新境界:微服务架构与容器化技术
在数字化时代的浪潮中,后端开发不断演进,涌现出创新的架构与技术。本文深入探讨了微服务架构和容器化技术如何重塑后端开发,提升系统的可维护性、可扩展性和部署效率。通过实际案例分析,我们揭示了这些技术背后的原理,并提供了实施的最佳实践和面临的挑战,为后端开发者提供一条清晰的技术升级路径。
39 3
|
20天前
|
负载均衡 监控 API
探索微服务架构中的API网关模式
【7月更文挑战第30天】在微服务架构的复杂网络中,API网关扮演着交通枢纽的角色,不仅简化了客户端与各微服务的交互,还提升了系统的安全性和可维护性。本文将深入探讨API网关的设计原则、核心功能以及在实际应用中的部署策略,旨在为后端开发者提供一套完整的API网关解决方案。