您的位置  > 互联网

API-认证、授权和凭证-洞见单点登录(SSO)

身份验证的一个常见用例是单点登录。 单点登录主要解决一次登录访问多个独立应用的问题。 在单点登录解决方案出现之前,每个应用程序都需要独立登录来维护自己的会话。 相关技术方案已经非常成熟,主要包括以下内容:

授权

授权主要解决你能做什么的问题。 从解决方案来看,有以下几种:

如果你想了解更多关于授权的知识,可以参考这篇文章:

授权| 凤凰建筑资质

证书的目的是解决认证授权后如何携带认证授权信息的问题。 在单一应用时代,主流的解决方案是以基于HTTP协议机制为代表的服务器端状态存储技术。

由于HTTP协议本身是无状态的,为了维护一个()而不是每次访问都重新进行认证和授权,客户端即浏览器需要存储一个服务器返回的凭证信息。 该凭证信息通常是一个随机字符串,用于表示用户的会话 ID。 浏览器每次发出请求时都会在 HTTP 中携带此信息。 应用程序获得会话ID后,从内存或缓存(Cache)中查询用户的信息,从而定位特定用户并维护会话。

这种古老的解决方案具有以下固有的优势: 凤凰建筑

在我们进入分布式系统时代之前,一切都很棒。

分布式系统

分布式系统和单体系统之间的主要区别是状态管理。 分布式系统将单个系统的有状态部分转移到中间件进行管理,很容易实现水平扩展,提高系统的峰值处理能力。 在架构的认证和授权部分,分布式和单体没有区别。 唯一改变的是国家持有凭证部分。

我们知道,单个应用程序在服务器端管理用户会话信息,客户端只保存会话ID。 如果服务器想要转移这个用户会话状态,有两种处理思路:

为什么在分布式系统中共享状态如此困难? 这是因为分布式系统中有一个不可能三角理论:CAP。 这个理论的简单理解就是,在分布式系统中,由于网络不可能做到绝对可靠(分区容错:),所以只能在一致性()和可靠性()之间进行选择。

例如,上面提到的三种服务器端解决方案实际上牺牲了CAP的某些方面。 例如,在第一个中心化存储方案中,我们放弃了中心化存储的分区容错能力。 一旦其网络被分区,整个集群将不可用。 在第二个会话复制解决方案中,我们牺牲了可用性。 当节点正在同步会话数据时,整个服务将暂时不可用。 在第三个会话粘性解决方案中,我们牺牲了一致性。 一旦某个节点宕机,整个集群的数据就会因为该节点的数据丢失而达到不一致的状态。

智威汤逊

如果你不了解JWT,可以先阅读这两篇文章:

智威汤逊 | 智威汤逊谈论的难点

由于JWT没有太多限制,因此很容易造成滥用问题并导致很多误解。 例如,以下一些问题:

相信看完上面的一些问题,你对JWT的“简单性和安全性”有了新的认识。 这还没完,JWT还存在以下问题:

JWT解决了分布式系统中CAP的局限性带来的问题,但也带来了一些新的问题。 所以不能说JWT是分布式系统中的完美替代品。

那么 JWT 的最佳用例是什么? 这篇停止使用 JWT 的文章给出了以下结论:JWT 更适合在分布式系统中用作一次性令牌。 分布式系统继续用于会话管理,但可以在鉴权认证后生成JWT,作为分布式系统内部服务调用之间的一次性令牌。

我们通过一个例子来了解一下分布式系统中的认证授权场景。

一个例子

用户通过 HTTPS 访问我们的应用程序。 当请求发送到微服务网关层()时,网关检测到HTTP中没有这样的键值对,并重定向到SSO登录页面。 用户通过 SSO 登录我们的应用程序。 用户信息存储在AD/LDAP等系统中。 管理员预先为用户配置角色权限。 我们选择 OIDC 作为 SSO 集成解决方案。 OIDC 集成了 AD/LDAP,当用户提供正确的用户名和密码时,SSO 重定向到网关。 网关生成一个键值对,并通过 HTTP Set- 将其设置到用户的浏览器。 浏览器重新向网关发起请求,网关通过查询其缓存或中间件(如在Redis中存储会话信息)中的信息来确认用户的身份信息。 然后网关请求Auth服务使用其私钥签名生成JWT证书。 JWT可以存储部分用户信息和角色信息,这些信息可以从中间件或AD/LDAP中查询。 然后网关通过反向代理将此 JWT 凭证转发到内部 BFF 服务,然后请求到达内部域微服务。 各个字段的微服务收到请求后,首先从HTTP中取出JWT凭证。 在执行真正的业务逻辑之前,首先使用之前从Auth服务同步的公钥。 Auth 服务通过类似于 /.well-known/jwks.json 的 API 提供 JWT 公钥的分发。 关于 . 前缀,您可以阅读 RFC 5785 以获取更多信息。 在jwks.json文件中我们可以找到JWK或JSON Web Key,这是我们用来验证签名的公钥。 验证 JWT 的逻辑是微服务的常见部分。 一般来说,可以开发一个SDK包来完成这项常见的工作。 为了提高性能,可以使用缓存技术定期从Auth同步公钥。 获取公钥并验证成功后,取出JWT获取用户信息和角色权限。

整个过程是这样的,我们得到以下好处:

架构总是在进化的,也许我们还没完全解决分布式系统的很多问题就已经进入了云原生时代。

云原生系统

如果你对云原生应用开发不了解,可以先阅读我的K8S云原生应用开发笔记。 云原生系统实际上并不是后分布式系统时代。 两者都是解决不同场景下问题的方案。

在认证和授权方面,云原生系统的优势在于它们可以通过服务网格(Mesh)来完成业务系统中一些常见方面的工作。 比如我们在分布式系统中遇到的验证JWT的SDK,其实可以放到服务网格中的()中实现,让业务应用更加专注于特定的业务领域。

由于本文不主要讨论云原生,因此对这部分感兴趣的可以参考以下两篇文章进一步了解:

Mesh架构下认证授权总结

由于篇幅和能力的限制,本文只能从较高的层面回顾一下不同架构演进过程中与架构安全相关的认证、授权、凭证技术的发展历程。 由于这些技术涉及大量的技术标准和实践,很难在一篇文章中详细分享这些技术,更不用说如何实现了。 但有了这些理论支持和最佳实践,希望能给大家在实施过程中多一份指导。 如果您想了解更多,可以参考文章中的参考文章链接。

最后,技术总是在发展,但新技术并不总是比旧技术“先进”。 正如文中对 JWT 的分析和比较,技术方案总是充满了各种权衡。 作为工程师,我们能做的就是了解这些技术的历史背景和局限性,选择最适合项目需求的技术方案。