


























最近在工作中遇到了一个问题,在实现OAuth2的过程中,发现公司的实际落地与理论不完全相同。故此复习一下。
OAuth2(OAuth2.0)是一个开放标准的授权框架,用于第三方应用(客户端)在取得用户(资源所有者)的授权下,可以访问用户敏感信息。而无需向第三方应用暴露账号密码。
设计之初聚焦于权限管理
OAuth2诞生的初衷是为了避免第三方应用获取用户的原始密码,同时让用户(资源所有者)自主控制第三方应用(客户端)对自己敏感信息的访问权限(比如只读,修改,删除),其本质是"授权第三方有限度的使用资源"。
本身不参与认证
在OAuth2流程中,用户身份的验证始终由资源所有者的平台负责(比如微信,GITHUB),由它们提供Login页面。
OAuth本身不参与用户身份的验证,它只是在验证通过后,传递"已授权"的凭证。
仅仅是一份授权证明
OAuth2最终发放的是"访问令牌(Access Token)",它仅仅代表用户允许第三方应用如何访问特定资源,不包含用户身份信息,也不能作为用户身份的证明。
举个例子,使用该Access Token在https://www.jwt.io/ 中解析。eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjEyMzQ1Niwic2NvcGUiOiJwcm9maWxlIG9wZW5pZCIsImV4cCI6MTczMzcwMjQwMCwiaWF0IjoxNzMzNjk4ODAwLCJpc3MiOiJodHRwczovL2F1dGguZXhhbXBsZS5jb20ifQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
OAuth2定义了4个核心角色,所有流程都围绕这4个角色展开
| 角色 | 含义 | 举个例子 |
|---|---|---|
| 资源所有者 | 用户本身,有权决定是否授权客户端访问自己的资源 | 使用微信的你 |
| 客户端 | 第三方应用,希望访问用户(也就是你)的敏感信息 | 比如小红书希望访问你微信上的照片,头像,昵称等![]() |
| 授权服务器 | 由资源服务器提供,验证用户的身份,生成授权凭证(Access Token) | 微信的授权服务器 ![]() |
| 资源服务器 | 存储受保护资源的服务器,接收并验证客户端的Access Token | 微信的用户信息服务器(存储你的头像、昵称等,只有验证令牌后才返回)。![]() |
OAuth2根据客户端的类型(是否有服务器,是否能安全存储密钥)定了多种Grant Type。
授权码模式(Authorization Code)
隐式模式(Implicit)
密码模式(Resource Owner Password Credentials)
客户端模式(Client Credentials)
重点关注授权码模式(Authorization Code)即可,剩下的三种纯属凑数。谁敢在生产环境暴露密钥?谁又能保证密钥永远不会泄露?
OAuth2中有3种关键凭证,用于确保授权流程的安全性
授权码(Authorization Code)
访问令牌(Access Token)
刷新令牌(Refresh Token)

Q1:授权服务器生成Code之后,redirect_uri重定向回前端还是后端?
授权服务器生成 Code 后,通过 redirect_uri 首先发送给第三方客户端的前端(浏览器 / APP),再由前端中转到客户端的后端,最终由后端用 Code 交换 Access Token。
Q2:为什么Code一定要重定向回前端,后端不行吗?
可以,但会造成如下几个问题:
- 用户授权流程的缺失
当用户同意授权后,如果直接发给后端。那么用户的前端页面完全不知道授权结果,比如用户在微信登录页授权后,浏览器还停留在微信页面,不知道该跳转回到客户端哪里。授权流程被割裂,对于用户体验不好。- 无法验证客户端的合法性
如果直接发后端,授权服务器只能通过RedirectUri来判断,但这个地址可能会被伪造,比如攻击者伪装成客户端后端地址,诱导授权服务器把 Code 发给他。HTTPS的中间人攻击也是这个原理。
而通过前端重定向,「用户的上下文」就是天然的验证:用户是从客户端前端跳转去授权服务器的,授权后跳回客户端前端,相当于用户 “背书” 了这个客户端的合法性,避免了攻击者伪造后端接收 Code 的风险。- 网络可达性问题
后端地址可能是企业内网,也可能是有防火墙,跳板机,堡垒机等保护。授权服务器根本无法直接访问这些后端接口。
而网页前端天生自带公网IP,授权服务器只需通过 “跳转” 把 Code 交给前端,再由前端中转给后端,完美解决了 “授权服务器找不到客户端后端” 的问题
SSO是一种"业务目标",而OAuth2是实现该目标的常用方案之一。它们是两个不同的概念,既不冲突也不等同,而是 “目标与工具” 的关系。
OAuth2可以实现SSO,但不是SSO的唯一实现方式。还有其它协议,比如SAML2.0,CAS,以及非常轻量化的Cookie共享,Ticket自包含等方案。
它们混淆的根源在于:
场景高度重叠
OAuth2最常见的场景就是第三方登录,比如使用微信登录美团,淘宝等第三方客户端。
在用户的视角下,只要使用微信登录,就能登录多个应用一气呵成,很流畅很润,对于用户最直观的感受就是,这就是SSO。

在开发者的视角下,对接第三方登录时,市面上90%的方案就是OAuth2协议,久而久之就形成了刻板印象与路径依赖。
概念边界很模糊,认证与授权往往同时出现
主流基于OAuth2的SSO方案,不会只做"身份认证",还会同步处理"权限校验"。而OAuth2刚好能同时解决,导致SSO与OAuth2深度绑定,难以拆分理解
我就经常混淆.NET中app.UseAuthentication()与app.UseAuthorization() ,他们两个的单词拼写都很接近,更别说概念了。
OAuth2的核心是授权,即使不用来做SSO,它也能单独解决"第三方应用访问用户资源"的问题。
SSO的核心是认证,即使不用OAuth2,它也能解决"重复登录"的问题,比如使用JWT形式的Ticket,也能实现SSO,与授权无关。
在文章中,一直强调OAuth2是对资源的管理,好像跟认证没啥关系啊。为什么能扯上关系?
正所谓,弹道也是道,枪法也是法,保时捷也是劫。
当今互联网识别用户唯一标识的主流,分别是Email&Phone。
我们可以把这两者当作一种资源去申请,申请到之后,跟自己数据库匹配,如果存在那就直接颁发ticket/cookie,如果不匹配,就自动创建用户并颁发ticket/cookie。 从而以一种曲线救国的方式完成了免密登录。

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



埋了一个彩蛋,再次解释了为什么Code一定要重定向回前端。
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。