“干中学”:SSO 单点登录是登录一次,多个系统使用,那我之前做的新登录后旧 Token 失效是什么?
看到一篇微信公众号文章:Session、Token、JWT、SSO、OAuth 认证体系详解,里面对于使用过的一些技术概念做了阐释。突然发现 SSO 单点登录的定义是“让用户登录一次就能访问多个相关但独立的系统”,那我之前做的新登录后旧 Token 失效是什么?
问了 chatgpt 给出一份相似功能对比(我的描述词是“用户登录会挤掉其他用户的登录状态”):
| 功能 | 作用 | 是否会挤掉其他登录 |
|---|---|---|
| SSO(Single Sign-On,单点登录) | 一个账号登录多个系统 | ❌ 默认不会 |
| 单点注销 SLO(Single Logout) | 一个系统退出,其他系统一起退出 | ✅ 会 |
| 会话互斥登录(Single Session / Kickout) | 同一个账号只能一个地方在线 | ✅ 会 |
| 多端登录控制 | 限制 PC、手机、浏览器数量 | 可配置 |
| Token 吊销 | 新登录后旧 Token 失效 | ✅ 会 |
最符合我表达意思的是 Token 吊销的功能,那是给小程序和 APP 通讯的时候,有需求针对账号做一个新登录退出所有其他的该账号的登录功能。主要是通过 Laravel 中间件在请求前截取 jwt 内容,判断当前账号如果开启了这个功能并且当前请求的 Token 有效时间如果小于存储的有效时间,就把当前的 Token 给删除掉,只保留最新的一条。登录状态一般是 redis 存储,也有做持久化存储的。
当然这是多端之间的通讯,如果是使用 Session 通讯的前后端不分离的场景下,要求只有一个账号登录,对应的功能就是这里的会话互斥登录功能。多端登录控制 也比较好理解,比如移动端微信搜索框下就有一个已登录设备管理功能,可以管理其他端的登录状态。类似的 ezbookkeeping 做的 设备和会话 功能,就是把所有登录的状态都显示在一个列表,可以主动注销掉其他的登录。按照这个范例,其实之前项目也可以这样做,一目了然哪些设备和会话有在登录。
说到这里,对于什么是 SSO 单点登录功能还是有点迷茫。如果说登录到其他系统就算 SSO,那么 Oauth,还有前公司的微服务架构实现的注册中心也算了。询问了 chatgpt 确认了这一点:
SSO 是一种业务目标/能力,不是一种具体协议。OAuth、CAS、SAML、OIDC 等都是实现 SSO 的技术方案;JWT 则不是 SSO 协议,而通常是 SSO 体系里用于传递身份信息的一种 Token 格式。
| 方案 | 定位 | 现在使用情况 |
|---|---|---|
| CAS | 专门做SSO | 老企业很多 |
| SAML | 企业身份联邦 | 大型企业常见 |
| OAuth2 | 授权协议 | 广泛使用 |
| OIDC | OAuth+登录 | 现在主流 |
| JWT | Token格式 | 经常配合OIDC |
| Session共享 | 传统SSO方案 | 小型系统 |
CAS 在前公司的仪器管理系统里遇到过,校内用户通过统一身份认证进行授权登录,实现协议据说就是 CAS。大部分实验室和高校内部系统都支持该协议。
OAuth2 是在做一个站点免登录跳转到另一个站点的需求时接触到的。一开始看到 oauth.php 中的 providers 和 consumers 是懵的,因为跟之前接触过的微信小程序的授权登录不太一样。
翻到调用的原版的 Oauth2.0 三方依赖里,有 server/client 的概念,到了调用层就变成了 providers 和 consumers。一个站点即是 oauth 服务提供商,又是服务的消费者。所以在 A 站点需要免登录到 B 站点时,给 B 站点配置一个 A 站点的 provider,再给 A 站点配置一个 B 站点的 consumer...因为是互为表里的关系,所以看着有点乱。A 跳转到 B 的时候,携带了 A 站点标识,然后 B 站点 读取 A 站点的 provider,存在就发起 oauth 验证申请。因为是重定向可以直接获取到 A 站点登录用户的信息,返回的 access_token 中也携带了 A 站点用户的 id。之后再通过 access_token 去拿用户信息就简单了。
所以实现的底层调用还是 Oauth2.0,只不过业务上套了一层调用混乱的代码,导致阅读起来有点困难。
微信小程序的授权登录是拿 code 换的 access_token,然后获取到手机号、openId 等信息,之后根据手机号判断系统用户是否存在,有就直接登录,没有就创建账号。其实是差不多的逻辑。
微信手机号授权登录属于 OAuth2 思路的第三方身份认证;App 手机号快捷登录属于运营商身份认证服务;它们都不是 SSO,而是“登录方式/身份提供方”。最终通常都会接入自己的 OAuth2/OIDC 认证中心,再给业务系统签发自己的 Token。
一般的如微信的手机号授权登录跟 App 端的手机号快捷登录还不太一样。
微信小程序手机号快速验证:不是标准 OAuth 2.0 流程,但设计思想类似 OAuth 的授权模式。
App 端手机号快捷登录(运营商一键登录):通常也不是 OAuth 2.0,而是运营商自定义的认证协议。
| 功能 | 是否 OAuth2 | 本质 |
|---|---|---|
| 微信开放平台登录 | 接近 OAuth2 | 第三方身份认证 |
| 微信小程序手机号授权 | 类似 OAuth 授权码 | 手机号身份授权 |
| App 手机号快捷登录 | 通常不是 OAuth2 | 运营商认证 |
| Apple 登录 | OAuth2 + OIDC | 标准身份认证 |
| Google 登录 | OAuth2 + OIDC | 标准身份认证 |
| 企业 SSO | OAuth2/OIDC/SAML/CAS | 统一身份认证 |
最终结论:
OAuth2 是“授权协议”;OIDC 是“登录协议”;微信手机号授权和运营商快捷登录是“身份认证服务”,借用了 OAuth 的思想,但不是 OAuth2 标准实现。
本作品采用 知识共享署名-相同方式共享 4.0 国际许可协议 进行许可。
海滨擎蟹
微信
支付宝