为什么OAuth2与SSO经常混为一谈?

news/2025/11/8 21:29:30/文章来源:https://www.cnblogs.com/lmy5215006/p/19167012

简介

最近在工作中遇到了一个问题,在实现OAuth2的过程中,发现公司的实际落地与理论不完全相同。故此复习一下。

What is OAuth2?

OAuth2(OAuth2.0)是一个开放标准的授权框架,用于第三方应用(客户端)在取得用户(资源所有者)的授权下,可以访问用户敏感信息。而无需向第三方应用暴露账号密码

核心是"授权"而非"认证"

  1. 设计之初聚焦于权限管理
    OAuth2诞生的初衷是为了避免第三方应用获取用户的原始密码,同时让用户(资源所有者)自主控制第三方应用(客户端)对自己敏感信息的访问权限(比如只读,修改,删除),其本质是"授权第三方有限度的使用资源"

  2. 本身不参与认证
    在OAuth2流程中,用户身份的验证始终由资源所有者的平台负责(比如微信,GITHUB),由它们提供Login页面。
    OAuth本身不参与用户身份的验证,它只是在验证通过后,传递"已授权"的凭证

  3. 仅仅是一份授权证明
    OAuth2最终发放的是"访问令牌(Access Token)",它仅仅代表用户允许第三方应用如何访问特定资源,不包含用户身份信息,也不能作为用户身份的证明。

举个例子,使用该Access Token在https://www.jwt.io/ 中解析。eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjEyMzQ1Niwic2NvcGUiOiJwcm9maWxlIG9wZW5pZCIsImV4cCI6MTczMzcwMjQwMCwiaWF0IjoxNzMzNjk4ODAwLCJpc3MiOiJodHRwczovL2F1dGguZXhhbXBsZS5jb20ifQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
image

核心角色

OAuth2定义了4个核心角色,所有流程都围绕这4个角色展开

角色 含义 举个例子
资源所有者 用户本身,有权决定是否授权客户端访问自己的资源 使用微信的你
客户端 第三方应用,希望访问用户(也就是你)的敏感信息 比如小红书希望访问你微信上的照片,头像,昵称等image
授权服务器 由资源服务器提供,验证用户的身份,生成授权凭证(Access Token) 微信的授权服务器 image
资源服务器 存储受保护资源的服务器,接收并验证客户端的Access Token 微信的用户信息服务器(存储你的头像、昵称等,只有验证令牌后才返回)。image

核心授权类型(Grant Type)

OAuth2根据客户端的类型(是否有服务器,是否能安全存储密钥)定了多种Grant Type。

  1. 授权码模式(Authorization Code)

    • 适用场景: 有自己服务器的客户端,能够安全存储客户端密钥,不会暴露给前端
    • 特点: 通过授权码间接获取访问令牌,是最常用也是最安全的模式。
  2. 隐式模式(Implicit)

    • 适用场景: 有自己服务器的客户端(比如无需与后端交互的纯前端应用),无法安全存储客户端密钥(密钥会暴露在前端代码中)
    • 特点:跳过“授权码”步骤,直接从授权服务器获取访问令牌(通过URL片段返回),不返回刷新令牌。
    • 缺点:访问令牌直接暴露在前端,安全性较低(可能被拦截)。
  3. 密码模式(Resource Owner Password Credentials)

    • 适用场景:客户端与资源所有者高度信任(如公司内部应用),用户愿意向客户端提供账号密码。
    • 流程:用户直接向客户端输入账号密码,客户端拿着密码向授权服务器请求访问令牌(如“公司内部APP用域账号密码登录,获取员工信息系统的访问权限”)。
    • 缺点:客户端获取了用户密码,违背OAuth“不暴露密码”的初衷。
  4. 客户端模式(Client Credentials)

    • 适用场景:客户端访问自己的资源(非用户个人资源),无需用户授权。
    • 流程:客户端直接用自己的客户端ID和密钥向授权服务器请求访问令牌(如“天气APP的后端服务,用自己的凭证获取天气数据API的访问权限”)。

重点关注授权码模式(Authorization Code)即可,剩下的三种纯属凑数。谁敢在生产环境暴露密钥?谁又能保证密钥永远不会泄露?

核心凭证

OAuth2中有3种关键凭证,用于确保授权流程的安全性

  1. 授权码(Authorization Code)

    • 短期有效(几分钟),由授权服务器在用户同意授权后生成。
    • 仅能使用一次,兑换令牌后失效,避免被劫持后重复使用。
  2. 访问令牌(Access Token)

    • 客户端访问资源服务器的"key",包含了授权范围(比如只能访问头像,不能访问手机号)
    • 通常为JWT,资源服务器通过它验证客户端的访问权限。
  3. 刷新令牌(Refresh Token)

    • 长期有效(几天到几个月),用户在Access Token过期后,无需重新授权,直接获取Access Token。

Authorization Code 核心流程

image

Q1:授权服务器生成Code之后,redirect_uri重定向回前端还是后端?
授权服务器生成 Code 后,通过 redirect_uri 首先发送给第三方客户端的前端(浏览器 / APP),再由前端中转到客户端的后端,最终由后端用 Code 交换 Access Token。

Q2:为什么Code一定要重定向回前端,后端不行吗?
可以,但会造成如下几个问题:

  1. 用户授权流程的缺失
    当用户同意授权后,如果直接发给后端。那么用户的前端页面完全不知道授权结果,比如用户在微信登录页授权后,浏览器还停留在微信页面,不知道该跳转回到客户端哪里。授权流程被割裂,对于用户体验不好。
  2. 无法验证客户端的合法性
    如果直接发后端,授权服务器只能通过RedirectUri来判断,但这个地址可能会被伪造,比如攻击者伪装成客户端后端地址,诱导授权服务器把 Code 发给他。HTTPS的中间人攻击也是这个原理。
    而通过前端重定向,「用户的上下文」就是天然的验证:用户是从客户端前端跳转去授权服务器的,授权后跳回客户端前端,相当于用户 “背书” 了这个客户端的合法性,避免了攻击者伪造后端接收 Code 的风险。
  3. 网络可达性问题
    后端地址可能是企业内网,也可能是有防火墙,跳板机,堡垒机等保护。授权服务器根本无法直接访问这些后端接口
    而网页前端天生自带公网IP,授权服务器只需通过 “跳转” 把 Code 交给前端,再由前端中转给后端,完美解决了 “授权服务器找不到客户端后端” 的问题

为什么OAuth2与SSO经常混为一谈?

SSO是一种"业务目标",而OAuth2是实现该目标的常用方案之一。它们是两个不同的概念,既不冲突也不等同,而是 “目标与工具” 的关系。
OAuth2可以实现SSO,但不是SSO的唯一实现方式。还有其它协议,比如SAML2.0,CAS,以及非常轻量化的Cookie共享,Ticket自包含等方案。

它们混淆的根源在于:

  1. 场景高度重叠
    OAuth2最常见的场景就是第三方登录,比如使用微信登录美团,淘宝等第三方客户端。
    在用户的视角下,只要使用微信登录,就能登录多个应用一气呵成,很流畅很润,对于用户最直观的感受就是,这就是SSO。
    image
    在开发者的视角下,对接第三方登录时,市面上90%的方案就是OAuth2协议,久而久之就形成了刻板印象与路径依赖。

  2. 概念边界很模糊,认证与授权往往同时出现
    主流基于OAuth2的SSO方案,不会只做"身份认证",还会同步处理"权限校验"。而OAuth2刚好能同时解决,导致SSO与OAuth2深度绑定,难以拆分理解

我就经常混淆.NET中app.UseAuthentication()与app.UseAuthorization() ,他们两个的单词拼写都很接近,更别说概念了。

两者核心差异

OAuth2的核心是授权,即使不用来做SSO,它也能单独解决"第三方应用访问用户资源"的问题。
SSO的核心是认证,即使不用OAuth2,它也能解决"重复登录"的问题,比如使用JWT形式的Ticket,也能实现SSO,与授权无关。

OAuth2如何勾搭上SSO的?

在文章中,一直强调OAuth2是对资源的管理,好像跟认证没啥关系啊。为什么能扯上关系?
正所谓,弹道也是道,枪法也是法,保时捷也是劫
当今互联网识别用户唯一标识的主流,分别是Email&Phone。
我们可以把这两者当作一种资源去申请,申请到之后,跟自己数据库匹配,如果存在那就直接颁发token/cookie,如果不匹配,就自动创建用户并颁发token/cookie。 从而以一种曲线救国的方式完成了免密登录。
image

简单DEMO

https://gitee.com/lmy5215006/auth-learning-work
image
image
image

埋了一个彩蛋,再次解释了为什么Code一定要重定向回前端。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/959995.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

完整教程:高斯隐马尔可夫模型:原理与应用详解

完整教程:高斯隐马尔可夫模型:原理与应用详解pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", &…

计算机毕业设计选题推荐:基于SpringBoot和Vue的快递物流仓库管理系统【源码+文档+调试】 - 实践

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

耄大厨——AI厨师智能体(3-程序调用)

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

flask: 保存异常时的错误信息和堆栈到日志

一,代码: 定义异常的处理 app.py import os from dotenv import load_dotenvfrom flask import Flask,jsonifyfrom flask_sqlalchemy import SQLAlchemy# 加载变量 dotenv_path = os.path.join(os.path.dirname(__fi…

2020:【例4.5】第几项

2020:【例4.5】第几项 时间限制: 1000 ms 内存限制: 65536 KB 提交数:91171 通过数: 63263 【题目描述】 对于正整数n,m ,求s=1+2+3……+n ,当加到第几项时,s 的值会超过m ? 【输入】 输入m 。 【输出…

Camsys 时间戳信息简介

不同平台时间戳介绍 1.征程 3 平台 其中 u64 timestamps: 硬件时间戳,是跟 CPU 一起用的 64 bit system counter,1s 是 24M 个 clock。 FS 的时候从硬件寄存器读取。读取的值除以 24000 是毫秒,除以 24000000 是秒…

git新建分支,以及推送本地代码到新建分支

第一步:在GitHub上创建新分支 打开GitHub仓库页面 点击"Branches"超链接 输入新分支名(如MD)并创建 ⚠️ 注意:新建的分支默认与当前默认分支(通常是master)内容一致 第二步、本地初始化并关联远程仓库…

20251108——读后感4

使用Git等版本控制工具很重要。团队开发时,每个人的代码变更都能被跟踪,出现问题可快速回滚。比如团队开发一个功能,有人误改代码导致系统出错,通过Git的版本历史能迅速找到问题版本并修复。

ESP-IDF开发环境搭建(Fedora)

ESP-IDF开发环境搭建(Fedora)如果想在Fedora里进行SSH外部连接,需要修改一些地方:sudo vi /etc/ssh/ssh_config,在里面将被注释的Port 22打开; 回到终端执行systemctl enable sshd.service 终端执行systemctl st…

深入解析:【深入浅出PyTorch】--6.2.PyTorch进阶训练技巧2

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

Django `models.Field` 所有常见安装参数的完整清单与说明表

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

Java Redis “Sentinel(哨兵)与集群”面试清单(含超通俗生活案例与深度理解) - 实践

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

操作系统中的索引节点存放什么数据?

目录索引节点(inode)的核心内容1. 文件的元数据2. 指向数据块的指针3. 文件的类型信息关键点:inode 中不包含什么?一个生动的比喻总结表格索引节点(inode)的核心内容 可以把 inode 想象成一个文件的“身份证”或…

后缀学习笔记 | -er/-or -ee 系列 - 详解

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

应用于ElasticSearch的C++ API——elasticlient - 教程

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

CICD程序选型指南,Jenkins vs Arbess哪一款更好用?

CICD程序选型指南,Jenkins vs Arbess哪一款更好用?pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas&quo…

China Collegiate Programming Contest (CCPC) Jinan Site (The 3rd Universal Cup. Stage 17: Jinan) 题解

目录Problem A. The FoolProblem B. The MagicianProblem C. The EmpressoProblem D. The EmperorProblem E. The ChariotProblem F. The HermitProblem G. The Wheel of FortuneProblem H. StrengthProblem I. The Ha…

LLM 训练基础概念与流程简介

1. LLM 训练基础概念 1.1 预训练(Pretrain) LLM 首先要学习的并非直接与人交流,而是让网络参数中充满知识的墨水,“墨水” 理论上喝的越饱越好,产生大量的对世界的知识积累。 预训练就是让 Model 先埋头苦学大量基…

完整教程:Suppr超能文献的zotero插件-github项目的介绍

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

TensorRT 和 ONNX Runtime 推理优化实战:10 个降低延迟的工程技巧

模型速度的瓶颈往往不在算法本身。几毫秒的优化累积起来就能让用户感受到明显的性能提升。下面这些技术都是在生产环境跑出来的经验,不需要重构代码实施起来也相对简单并且效果显著。https://avoid.overfit.cn/post/4…