每日一博 | 盘点微服务架构下的诸多身份验证方式
联合作者:罗泽轩,API7.ai 技术专家、Apache APISIX PMC 成员
联合作者:赵士瑞,API7.ai 技术工程师,Apache APISIX Committer
身份认证是授予用户访问系统并授予使用系统的必要权限的过程。而提供了这一功能的服务,就是身份认证服务。
在传统的单体软件应用程序中,所有这些都发生在同一个应用程序中。但在微服务架构中,系统由多个服务组成,在这样的架构中,每个微服务都有自己的任务,因此为每个微服务分别实现授权和身份验证过程并不完全符合此原则。
本文将从传统服务架构和微服务架构下的身份认证方式区别进行讨论,并最终衡量微服务架构中身份认证服务的各种实现方式的优劣。
传统服务架构中的身份认证服务
在企业开发服务的早期,所有功能都是做到同一个应用程序里面的。我们把这种模式称之为 “单体”,以跟当下更为主流的 “微服务” 架构区分开来。
单体应用由单个不可分割的单元组成。它通常由各个业务线各自开发,但是部署时放入到同一个环境中。所有这些都紧密集成以在一个单元中提供所有功能。这一单元里拥有所需的所有资源。单体应用的好处在于部署迭代简单,适合业务线较少且比较独立的公司采用。
随着企业开发出来的业务越来越复杂,我们会发现单体服务已经无法满足现实生活里面快速迭代的需要了。我们需要把这个单体的巨无霸拆分一下,同时保证现有的各个功能间的调用能正常进行。这时候,ESB(企业服务总线)便应运而生了。
所谓的 “企业服务总线”,就是一根连接各个企业服务的管道。ESB 的存在是为了集成基于不同协议的不同服务,ESB 做了消息的转化、解释以及路由的工作,以此来让不同的服务互联互通。从名称就能知道,它的概念借鉴了计算机组成原理中的通信模型 —— 总线,所有需要和外部系统通信的系统,统统接入 ESB,就可以利用现有的系统构建一个全新的松耦合的异构的分布式系统。
ESB 做了消息的转换解释与路由等工作,让不同的服务互联互通。传统的 ESB 的服务调用方式是,每一次服务的调用者要向服务提供者进行服务交互请求时都必须通过中心的 ESB 来进行路由。
接下来将按照这两种情况,分别描述对应的身份认证功能的实现。
单体架构
单体架构下,用户身份验证和会话管理相对简单。身份认证和授权发生在同一个应用程序中,通常使用基于 session 的认证方案。一旦通过身份验证,就会创建一个会话并将其存储在服务器上,任何需要它的组件都可以访问它并用于通知和授权后续要求。会话 ID 被发送到客户端并用于应用程序的所有后续请求,以将请求与当前会话相关联。
ESB 架构
在 ESB 架构下,所有用户与服务之间,服务与服务之间全部通过 ESB 总线进行处理。由于 ESB 的架构是从单体拆分下来的,身份认证方式相对于单体架构并没有变化。
微服务架构中的身份认证服务
从单体架构迁移到微服务架构有很多优势,但微服务架构作为一种分布式架构,会存在更大的攻击面,共享用户上下文更加困难。因此微服务架构下需要有跟传统架构不一样的身份认证服务,才能响应更大的安全性挑战。
目前,我们可以把微服务架构下的身份认证服务分为以下三类:
- 通过每个微服务实现身份认证;
- 通过身份认证服务实现身份认证;
- 通过网关实现身份认证。 当然,每种做法都有自己特定的优缺点。
通过每个微服务实现身份认证
既然微服务架构是从单体架构拆分出来的,因此比较自然的过渡方式就是由每个微服务自己实现身份认证。
每个微服务都需要实现自己独立的安全性保障,并在每个入口点上强制执行。此方法使微服务团队能够自主决定如何实现其安全解决方案。但是,这种方法有几个缺点:
- 安全逻辑需要在每个微服务中重复实现,这会导致服务之间的代码重复。
- 它分散了开发团队的注意力,使其无法专注于其主要服务。
- 每个微服务都依赖于它不拥有的用户身份验证数据。
- 很难维护和监控。 完善这个解决方案的选择之一就是使用一个加载在每个微服务上的共享认证库。这个操作可以防止代码重复,开发团队将只关注他们的业务领域,但仍然存在这种改进无法解决的缺点。
因为共享的认证库仍然需要有对应的用户身份数据,而且还需要保证各个微服务使用同样版本的认证库。老实说,共享认证库更像是服务拆分不透彻的结果。
因此这种方式总结来说,优势在于实施速度快,独立性强;而劣势也比较明显,服务之间的代码重复、违反单一职责原则,较难维护。
通过身份认证服务实现身份认证
既然每个微服务自己实现身份认证难以维护,而使用共享认证库又违背了微服务拆分的本意,那么能不能把共享认证库升级成专门的身份认证服务呢?
在这种情况下,所有访问都通过同一服务进行控制,类似于单体应用里面的身份认证功能。每个业务服务都必须在执行操作时,向访问控制模块发送单独的授权请求。
但是,这种方法在一定程度上减慢了服务的运行速度,并增加了服务之间的互连量。并且各个微服务会依赖这个“单点”的身份认证服务。万一统一的身份认证服务出问题,会造成链式反应,带来二次伤害。
所以总结来看,这种方式虽然确保了每个微服务职责单一,使得身份认证功能更加集中。但是仍会造成单点依赖,进而增加请求延迟。
通过网关实现身份认证
迁移到微服务体系结构时,需要回答的问题之一是微服务之间如何通信。前面提到的 ESB 是种方案,但是更常见的选择则是采用 API 网关。
API 网关是所有请求的单个终端节点入口,它通过充当使用这些微服务的中央接口来提供灵活性。某个需要访问其他微服务的微服务(以下称之为“客户端”,以跟被它访问的微服务相区分)无权访问多个服务,而是需要向负责将其路由到上游服务的 API 网关发送请求。
由于 API 网关位于客户端访问的必经之路上,因此它是强制实施身份验证问题的绝佳选择。使用 API 网关可以减少延迟(调用身份验证服务),并确保身份验证过程在整个应用程序中保持一致。
举个例子,通过 APISIX 的 jwt-auth 插件,我们可以在网关上实现身份认证。
首先,我们需要规划若干个用户身份信息(名称、密钥等等),并将其配置到 APISIX 上。 其次,根据给定的用户密钥,向 APISIX 发起签名请求,得到这个用户的 JWT token。 接着,当客户端需要访问某个上游服务时,带上 JWT token,由 APISIX 作为 API 网关代理该访问。 最后,APISIX 会通过 JWT token,完成身份认证的操作。
当然,凡事有利就有弊,没有完全无劣势的技术选型。使用网关来完成身份认证,还是带来了少许单点问题。比起在每个微服务内完成身份认证,在网关上解决该问题,安全性相比会降低些。比如 API 网关被攻破之后,就可以访问该网关背后的任何微服务。但是风险是相对的,比起统一的身份认证服务,使用 API 网关的单点问题并没有那么严重。
因此这种方式操作起来,在优势上较为明显,比如可以有效保护后端微服务,微服务不用处理任何认证逻辑等。但同时还是会存有少许的单点依赖。
总结
在不同的场景下,我们会需要不同的身份认证方案。在单体应用中,身份认证发生在同一个应用程序中,服务端保存了所有的会话。进入微服务时代,单体应用演变为分布式服务,单体应用中的身份认证方式在微服务中并不适用。在微服务架构中,我们有上述提到的三种身份认证的方式可供选择。每种选择都有属于自己的利弊,需要根据具体的实际情况做具体分析。

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
React Native 0.71 发布,默认使用 TypeScript、恢复 PropTypes
React Native 0.71 版本正式发布,这是一个功能丰富的版本,包括:默认的 TypeScript、Flexbox Gap、恢复 PropTypes 和新架构更新等。 默认 TypeScript 从 0.71 版本开始,当你通过 React Native CLI 创建一个新的 React Native 应用时,你将默认得到一个 TypeScript 应用。 我们还直接从 react-native 包中提供内置的、更准确的 TypeScript 声明。这意味着你将不再需要 @types/react-native,并且类型将与 React Native 版本同步更新。 用 Flexbox gap 简化布局 通过 React Native,你可以使用 Flexbox 在不同的屏幕尺寸上灵活地布局组件。浏览器已经支持 Flexbox gap、rowGap 和 columnGap 属性,它们允许你指定 Flexbox 中所有项目之间的空间大小。 这些属性在 React Native 中已经被要求了很久,0.71 版本增加了对使用像素值定义的 gap 的初始支持。在未来的版本中,我们将增...
- 下一篇
Pyright —— Python 静态类型检查工具
Pyright 是微软开发的一个 Python 代码类型检查工具。 Pyright 的速度是mypy 的 5 倍以上。Pyright 使用 TypeScript 开发,无需 Python 环境支持。 官方表示创建Pyright 是为了解决像 mypy这些已有的 Python 类型检查器的问题。有以下值得关注的特性: 速度快:Pyright 比使用 Python 编写的 mypy 和其他检查器普遍快5倍或更多。它适用于大型 Python 源码仓库,支持在“观察(watch)”模式下运行,并在修改文件时执行快速增量更新。 可配置:Pyright支持灵活的配置,提供了对设置的细粒度控制,可以为源码库的不同子集指定不同的“执行环境”。每个环境都可以指定不同的 PYTHONPATH 设置、Python 语言版本和目标平台。 不依赖 Python 环境:Pyright 使用 TypeScript 编写,它不需要安装 Python 环境或导入的第三方软件包。 Pyright 包含一个命令行工具和一个 VS Code 的Language Server Protocol插件。
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS8安装Docker,最新的服务器搭配容器使用
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- SpringBoot2初体验,简单认识spring boot2并且搭建基础工程
- Windows10,CentOS7,CentOS8安装MongoDB4.0.16
- Windows10,CentOS7,CentOS8安装Nodejs环境
- SpringBoot2全家桶,快速入门学习开发网站教程
- CentOS8编译安装MySQL8.0.19