身份认证系列(一):应用工程实践篇

更新时间 3/8/2024

引言

身份认证在互联网应用中扮演着保护数据访问和用户隐私的重要角色,特别是对于企业内部应用而言更是至关重要。在本系列文章中,我们将从不同的角度探讨身份认证,并在本篇文章中重点介绍应用工程实践中的身份认证方式。

在各种应用程序中,身份认证通常采用以下两种常见技术:

  1. Cookie & Session:这是一种传统的身份认证机制,广泛应用于 Web 应用程序中,通常在浏览器中使用。它通过使用 cookie 和 session 来验证用户身份并维持会话状态。

  2. Bearer Token:这是一种更现代化的身份认证机制,不再依赖于浏览器中的 cookie,而是利用 HTTP 协议本身来进行身份验证。这种机制更适用于 API 场景,并可在移动应用程序中使用。

无论选择哪种方式,开发者都需要为自己的产品选择合适的身份认证方案,以确保数据安全性、用户隐私和良好的用户体验。

传统 Web 应用

曾经,我们使用 Java JSP 直接编写 Web 应用,使用 JSESSIONID 的方式识别用户,该会话 ID 将保存在客户端浏览器的 cookie 中,并在每次请求中携带。

然而,这种方法存在一些问题。由于 cookie 由浏览器管理并存储在客户端设备上,如果恶意攻击者窃取存储的会话 ID,攻击者就能够冒充用户身份访问该应用程序,从而造成安全风险。此外,开发人员有时无法为 cookie 和 session 设置合理的有效期和安全要求。

在开发这些应用程序时,开发人员通常需要为每个系统单独实现身份认证,这些系统是相互独立的,使用不同的身份体系,这使得开发人员必须重复进行这些工作。在这种情况下,单点登录(SSO)可以解决这些问题,它使用一个统一的身份认证系统,只需在每个独立的 Web 应用程序中进行少量集成工作,即可完成身份认证功能。

近年来,前端和后端技术取得了快速进步。开发人员开始迁移到更现代化的技术堆栈上,而那些由旧技术驱动的应用程序逐渐成为遗留平台。然而,有时我们可能面临着新的身份安全需求,却无法修改旧代码的情况。在这种情况下,一种可选的方法是使用反向代理中间件,在其中执行身份认证。当客户端到达应用程序之前,中间件将用户导向外部的新身份认证界面,让用户在新的界面登录,中间件获取用户的身份信息,并将这些信息附加到请求中传递给旧的应用程序。这使得开发人员能够在不修改旧代码的情况下为旧应用程序添加新的身份认证机制。

identity authentication in API7

Web 应用进化:前后端分离

随着新的前端技术如 Vue 和 React 的出现,Web 交互方式得到了革新。过去,用户需要填写并提交页面上的表单,使用 HTML 中的表单和按钮与后端进行交互,这种方式并不提供良好的用户体验。而现在,页面上的交互是实时的,开发者使用 JavaScript 脚本与后端 API 进行交互,提供更加一致和连续的体验。用户的交互方式从直接的 HTTP 请求转变为调用各种 API。

面向 Web 页面和面向 API 的身份认证机制有一些不同之处。尽管旧的 cookie 仍然可以使用,但它们并不适用于现代前端技术。新技术赋予开发者更多的代码表现力,使其能够执行更多、更复杂的操作。例如,有时我们需要在前端切换用户账号,但通过 cookie 直接在前端实现这一点是困难的(出于安全考虑,与用户身份相关的 cookie 通常被配置为 httpOnly,这意味着 JavaScript 脚本无法读取和操作它们)。

通常情况下,现代前端应用程序会自行管理用户会话。一旦用户登录成功,前端会管理后端生成的令牌(token),并在发起 API 调用时将其添加到请求头中,以便后端可以识别用户身份。API 使用令牌来标识用户信息。有多种技术手段可供选择,例如,开发者可以手动使用 JWT(JSON Web Token)实现令牌机制。在 JWT payload 存储用户 ID 等标识信息,并对其进行签名,以使后端能够验证令牌并获取用户身份信息。

然而,JWT 也存在一些缺陷,比如:

  • JWT 的过期时间是固定的,一旦签名完成就无法修改。由于通常不由后端存储,而只进行签名验证,因此无法吊销令牌,存在被盗用的风险。

  • Payload 数据以明文形式存储,可以被客户端解析,因此无法用于存储机密信息。

幸运的是,现在有了新的 JWT 规范来解决上述缺陷:JWT payload 中可以使用名为“jti”的字段来存储唯一标识 JWT 的 ID,它可以在后端缓存中存储以控制 JWT 的生命周期。此外,JWE(JSON Web Encryption)规范定义了一种加密的 JWT 扩展,结合了非对称加密和对称加密的优势,确保 payload 以密文形式传输,避免泄露。

进一步地,还有一些基于 JWT 的技术提供了更成熟的解决方案,比如 OpenID Connect。需要明确的是,OpenID Connect 并不依赖于 JWT,但它们可以一起使用。OpenID Connect 规范了访问令牌(Access Token)和刷新令牌(Refresh Token)的机制,开发者可以使用短期令牌来规避盗用风险。OpenID Connect 的生态系统也很繁荣,现在有很多服务器和客户端实现可以帮助开发者构建基于 OpenID Connect 协议的身份认证系统。此外,像 Keycloak 这样的开源身份认证解决方案也能帮助开发者实现安全的身份认证服务。

API7 authentication plugins

新的前端技术实践(例如 Next.js)逐渐尝试将服务器端渲染技术引入前端领域,这实际上是旧的 Web 开发范式的全新演进,结合 React 和后端程序,进一步改善用户体验。现在有更多的程序库(例如 NextAuth)可以帮助开发者在这种机制上实现身份认证,这些库让身份认证的过程开发者友对开发者更加友好。

API 网关与身份认证

让我们思考一下,我们使用的移动应用如何进行数据交互?是否也会使用 API?在移动应用中,没有像浏览器上的 cookie 机制用于存储用户会话,因此它更多地使用令牌通过 HTTP 请求头来传递。

那么 API 服务呢?一个成功的应用后台通常会有许多复杂的 API 系统,它们需要一个统一的身份认证机制,否则牵一发而动全身,开发者将不得不为每个服务实现相同的认证机制。

API 网关可以帮助我们解决这个问题,它可以统一处理类似于 cookie 或令牌的验证和解析工作,并将解析后的身份信息直接传递给后端服务,从而减少重复工作。Aapche APISIXAPI7 企业版也支持开箱即用的 OpenID Connect 认证功能,帮助用户直接集成身份认证服务。此外,API 网关还支持用户通过脚本编程的方式实现任何验证机制,因此即使使用自定义的身份认证机制,也可以在 API 网关上进行集成,简化应用程序开发。

总结

用户交互方式的发展推动了身份认证的进步,以 API 为中心的方式正在成为主流趋势,而 API 可能由微服务架构提供,这需要一个统一的身份认证机制以减少重复开发。因此,我们应该选择更现代化的机制,如 OpenID Connect 和 JWT,并且使用 API 网关可以为 API 开发提供更多功能。

微信咨询

获取方案