分布式系统服务劣势、多服务协调及 OAuth 2.0 授权认证解析
1. 分布式系统服务劣势
在分布式系统中,涉及多个服务的写请求必须在每个服务中都成功,否则就要在所有服务中失败、中止或回滚。写过程需要包含重试、回滚或补偿事务等步骤。同时,可能需要对各个服务进行定期审计,以验证引用完整性。
2. 多服务功能开发与部署协调
2.1 理论情况
当新功能涉及多个服务时,开发和部署需要在这些服务之间进行协调。例如,一个 API 服务可能依赖于其他服务。以 Rust Rocket RESTful API 服务和 React UI 服务为例,理论上,两个服务的功能开发可以并行进行。API 团队只需提供新 API 端点的规范,UI 团队可以开发新的 React 组件以及相关的 node.js 或 Express 服务器代码。由于 API 团队尚未提供返回实际数据的测试环境,UI 团队可以使用新 API 端点的模拟或存根响应进行开发,这种方法也适用于编写 UI 代码的单元测试。此外,团队还可以使用功能标志,在开发和预发布环境中选择性地展示未完成的功能,同时在生产环境中隐藏这些功能,方便其他开发者和利益相关者查看和讨论正在进行的工作。
2.2 实际问题
实际情况要复杂得多,即使是有丰富 API 使用经验的开发者和 UX 设计师,也可能难以理解一组新 API 端点的细节。在开发各自的服务时,API 开发者和 UI 开发者可能会发现一些微妙的问题,导致 API 需要更改,双方团队需要讨论解决方案,可能还会浪费一些已经完成的工作:
-
数据模型与 UX 不匹配
:例如,在为通知系统的模板开发版本控制功能时,UX 设计师可能会设计出考虑单个模板的版本控制 UX,但实际上模板可能由单独进行版本控制的子组件组成,这种混淆可能直到 UI 和 API 开发都在进行时才会被发现。
-
数据库查询效率问题
:API 团队在开发过程中可能会发现,新的 API 端点需要低效的数据库查询,如过大的 SELECT 查询或大表之间的 JOIN 操作。
-
API 请求和处理复杂
:对于 REST 或 RPC API(非 GraphQL),用户可能需要进行多次 API 请求,并对响应进行复杂的后处理操作,才能将数据返回给请求者或显示在 UI 上。或者,提供的 API 可能会获取比 UI 所需更多的数据,从而导致不必要的延迟。对于内部开发的 API,UI 团队可能希望请求对 API 进行重新设计和改进,以实现更简单、更高效的 API 请求。
3. 服务接口
服务可以用不同的语言编写,并通过文本或二进制协议相互通信。对于 JSON 或 XML 等文本协议,这些字符串需要在对象之间进行转换。还需要额外的代码来验证缺失字段,并处理错误和异常。为了实现优雅降级,服务可能需要处理包含缺失字段的对象。为了应对依赖服务返回此类数据的情况,可能需要实施备份步骤,如缓存依赖服务的数据并返回旧数据,或者自己返回包含缺失字段的数据,这可能会导致实现与文档不一致。
4. 授权与认证概述
4.1 授权与认证的定义
授权是给予用户(个人或系统)访问特定资源或功能的权限的过程,而认证是对用户身份的验证。OAuth 2.0 是一种常见的授权算法,OpenID Connect 是 OAuth 2.0 的认证扩展。认证和授权/访问控制是服务的典型安全要求。
4.2 常见误解
网上常见的“使用 OAuth2 登录”的说法是错误的,这种说法混淆了授权和认证的不同概念。
5. 简单登录与基于 cookie 的认证
5.1 认证过程
简单登录是最基本的认证类型,用户输入(标识符,密码)对,常见的如(用户名,密码)和(电子邮件,密码)。当用户提交用户名和密码时,后端会验证密码是否与关联的用户名匹配。为了安全起见,密码应该进行加盐和哈希处理。验证通过后,后端会为该用户创建一个会话,并创建一个 cookie,该 cookie 会存储在服务器内存和用户浏览器中。后续浏览器的请求将使用该会话 ID 进行认证,用户无需再次输入用户名和密码。
5.2 会话过期
会话有有限的持续时间,过期后用户必须重新输入用户名和密码。会话过期有两种类型的超时:绝对超时和非活动超时。绝对超时在指定时间段过去后终止会话,非活动超时在用户在指定时间段内未与应用程序交互后终止会话。
6. 单点登录
单点登录(SSO)允许用户使用一个主账户(如 Active Directory 账户)登录多个系统,通常使用安全断言标记语言(SAML)协议实现。2000 年代后期移动应用的出现带来了新的需求:
-
长会话机制
:由于 cookie 不适用于移动设备,需要一种新的机制来实现长会话,即用户关闭移动应用后仍能保持登录状态。
-
委托授权
:资源所有者可以将对部分资源的访问权限委托给指定的客户端。例如,用户可以授予某个应用查看其 Facebook 部分用户信息(如公共资料和生日)的权限,但不允许该应用在其墙上发布内容。
7. 简单登录的缺点
7.1 复杂性和可维护性差
简单登录(或一般的基于会话的认证)的大部分实现工作由应用程序开发者完成,包括登录端点和逻辑、用户名和加盐哈希密码的数据库表、密码创建和重置(包括 2FA 操作,如密码重置邮件)等。这意味着应用程序开发者需要遵守安全最佳实践。而在 OAuth 2.0 和 OpenID Connect 中,密码由单独的服务处理,应用程序开发者可以使用具有良好安全实践的第三方服务,降低了密码被黑客攻击的风险。此外,cookie 需要服务器维护状态,每个登录用户都需要服务器为其创建一个会话,如果有大量会话,内存开销可能会很大。而基于令牌的协议则没有内存开销。开发者还需要维护应用程序,以符合相关的用户隐私法规,如通用数据保护条例(GDPR)、加利福尼亚消费者隐私法案(CCPA)和健康保险可移植性和责任法案(HIPAA)。
7.2 无部分授权
简单登录没有部分访问控制权限的概念。用户可能希望为特定目的授予另一方对其账户的部分访问权限,但授予完全访问权限存在安全风险。例如,用户可能希望授予像 Mint 这样的预算应用查看其银行账户余额的权限,但不希望该应用具有转账等其他权限。如果银行应用仅支持简单登录,用户必须将其银行应用账户的用户名和密码提供给 Mint,这会使 Mint 获得对其银行账户的完全访问权限。
8. OAuth 2.0 流程
8.1 OAuth 2.0 术语
| 术语 | 定义 |
|---|---|
| 资源所有者 | 拥有数据或控制应用程序请求的某些操作的用户 |
| 客户端 | 请求资源的应用程序 |
| 授权服务器 | 用户用于授权权限的系统,如 accounts.google.com |
| 资源服务器 | 持有客户端所需数据的系统的 API,如 Google Contacts API |
| 授权授权 | 用户同意访问资源所需权限的证明 |
| 重定向 URI(回调) | 授权服务器重定向回客户端时的 URI 或目的地 |
| 访问令牌 | 客户端用于获取授权资源的密钥 |
| 范围 | 授权服务器理解的权限列表,客户端可以根据其所需资源请求特定的权限范围 |
8.2 客户端初始设置
应用程序(如 Mint 或 Yelp)需要与授权服务器(如 Google)进行一次性设置,以成为客户端并启用用户使用 OAuth。Google 会提供客户端 ID 和客户端密钥,客户端 ID 通常是一个长而唯一的字符串标识符,在前端通道的初始请求中传递;客户端密钥在令牌交换期间使用。
8.3 OAuth 2.0 流程步骤
graph LR
classDef startend fill:#F5EBFF,stroke:#BE8FED,stroke-width:2px;
classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px;
classDef decision fill:#FFF6CC,stroke:#FFBC52,stroke-width:2px;
A([开始]):::startend --> B(用户在客户端应用点击授权按钮):::process
B --> C(浏览器重定向到授权服务器):::process
C --> D{用户登录并同意授权?}:::decision
D -- 是 --> E(授权服务器重定向回客户端,携带授权码):::process
D -- 否 --> F(授权失败,返回错误信息):::process
E --> G(客户端使用授权码请求访问令牌):::process
G --> H(授权服务器验证授权码并返回访问令牌):::process
H --> I(客户端使用访问令牌请求资源):::process
I --> J([结束]):::startend
F --> J
- 获取用户授权 :用户在客户端应用(如 Yelp)上点击授予访问其 Google 账户某些数据的按钮,浏览器会重定向到授权服务器(如 Google 域名)。在重定向过程中,客户端通过查询参数向授权服务器传递配置信息,如客户端 ID、重定向 URI、请求的权限范围、响应类型等。
- 用户同意授权 :用户在授权服务器上登录并确认是否同意客户端请求的权限范围。如果用户同意,授权服务器会重定向回客户端应用的回调 URI,并携带授权码;如果用户不同意,会返回错误信息。
- 请求访问令牌 :客户端使用授权码向授权服务器发送 POST 请求,交换访问令牌。请求中包含客户端密钥,授权服务器验证授权码后,会返回访问令牌和状态信息。
- 请求资源 :客户端验证响应中的状态信息与发送给服务器的状态信息是否一致,然后使用访问令牌向资源服务器请求授权资源。访问令牌仅允许客户端访问请求的权限范围,超出范围的资源请求将被拒绝。
8.4 前后通道概念
引入前后通道的概念是为了解释为什么需要先获取授权码,再交换访问令牌。前通道通信是协议中各方都可观察到的通信,而后通道通信是至少一方无法观察到的通信,因此后通道更安全。例如,客户端与授权服务器之间的交互通过浏览器进行,属于前通道通信,授权码也通过浏览器传输。如果授权码被拦截,黑客也无法获取访问令牌,因为令牌交换发生在后通道。
综上所述,分布式系统中的服务存在诸多挑战,包括引用完整性、多服务协调等问题。而 OAuth 2.0 和 OpenID Connect 为解决认证和授权问题提供了更安全、灵活的方案,相比简单登录具有明显的优势。
9. 前后通道在 OAuth 2.0 中的作用深入分析
9.1 前通道的风险
前通道主要是指通过浏览器进行的通信。在 OAuth 2.0 流程中,用户点击客户端应用上的授权按钮后,浏览器重定向到授权服务器,这个过程以及授权码的传输都是在前通道完成的。浏览器虽然有一定的安全性,但也存在一些漏洞。例如,黑客可以通过恶意工具栏或者能够记录浏览器请求的机制来拦截授权码。如果授权码被拦截,由于令牌交换是在后通道进行的,黑客无法直接获取访问令牌,这在一定程度上保护了系统的安全性。
9.2 后通道的安全性
后通道通信是指至少一方无法观察到的通信。在 OAuth 2.0 中,客户端使用授权码向授权服务器请求访问令牌的过程就是在后通道进行的。以 SSL 加密的 HTTP 请求从客户端服务器到 Google API 服务器为例,这种通信方式更加安全,因为数据在传输过程中被加密,不易被窃取。即使授权码被拦截,黑客没有客户端密钥,也无法完成令牌交换,从而保证了访问令牌的安全性。
10. OAuth 2.0 与简单登录的对比总结
| 对比项 | 简单登录 | OAuth 2.0 |
|---|---|---|
| 安全性 | 应用开发者负责密码处理,存在密码被黑客攻击的风险;cookie 需服务器维护状态,有内存开销 | 密码由单独服务处理,使用第三方服务降低风险;基于令牌协议无内存开销 |
| 部分授权 | 无部分访问控制权限概念,只能授予完全访问权限,存在安全风险 | 可以根据需求请求特定的权限范围,实现部分授权 |
| 复杂度和可维护性 | 开发者需实现登录端点、数据库表、密码管理等,还要遵守隐私法规 | 开发者可使用第三方服务,减少实现和维护工作 |
11. 多服务协调的最佳实践建议
11.1 提前规划和沟通
在开发涉及多个服务的新功能之前,各服务团队应进行充分的沟通和规划。明确每个服务的职责和接口规范,提前发现可能存在的数据模型不匹配、数据库查询效率等问题,避免在开发过程中出现大量的返工。
11.2 使用模拟和存根
在 API 团队尚未提供实际测试环境时,UI 团队可以使用模拟或存根响应进行开发。这样可以并行推进开发工作,同时也有助于编写单元测试,提高开发效率。
11.3 功能标志的合理运用
团队可以使用功能标志来选择性地暴露未完成的功能。在开发和预发布环境中展示这些功能,方便其他开发者和利益相关者查看和讨论,及时发现问题并进行调整。
11.4 定期审计
对于分布式系统中的服务,定期进行审计是非常必要的。通过审计可以验证引用完整性,确保数据的一致性和准确性。
12. 未来发展趋势展望
12.1 分布式系统服务的优化
随着技术的不断发展,分布式系统中的服务将朝着更加高效、稳定的方向发展。未来可能会出现更先进的分布式事务处理机制,减少写请求的复杂性和风险。同时,对于服务接口的标准化和自动化处理也将得到进一步提升,降低不同语言和协议之间的通信成本。
12.2 认证和授权技术的创新
OAuth 2.0 和 OpenID Connect 已经成为认证和授权领域的主流技术,但随着安全需求的不断提高,未来可能会出现更加安全、灵活的认证和授权协议。例如,结合生物识别技术、区块链技术等,进一步提升用户身份验证的准确性和安全性。
12.3 多服务协调的智能化
在多服务协调方面,智能化的工具和平台将得到更广泛的应用。通过人工智能和机器学习技术,可以实现对服务依赖关系的自动分析和预测,提前发现潜在的问题并进行优化。同时,自动化的部署和配置管理也将提高多服务开发和部署的效率。
总之,分布式系统服务、多服务协调以及认证和授权技术都在不断发展和演变。我们需要持续关注这些领域的最新动态,不断学习和掌握新的技术和方法,以应对日益复杂的系统开发和安全挑战。在实际应用中,要根据具体的业务需求和场景,选择合适的技术和方案,确保系统的高效运行和数据的安全可靠。
超级会员免费看
4104

被折叠的 条评论
为什么被折叠?



