OAuth2 协议
为什么需要 OAuth 协议
第三方应用需要用户在其他平台的资源,但用户不愿、也不应暴露核心账号密码,怎么办?
OAuth2.0 协议的核心价值是解决「第三方应用访问用户在另一平台的资源」时的安全与信任问题,避免账号密码泄露和权限滥用。
我们假设这样的一个场景
在 A 需访问用户在 B 的相片资源的场景中,直接用账号密码验证的方案存在致命问题:
- 用户信任危机:用户需向 A 暴露 B 的账号密码,无法确认 A 是否会窃取、滥用这些核心凭证。
- 平台信任危机:B 无法保证 A 仅将账号密码用于即时访问,可能被 A 存储、批量收集,导致用户信息泄露风险。
- 权限无边界:账号密码是最高权限凭证,一旦泄露,攻击者或恶意 A 可对用户在 B 的资源执行任意操作(如删改相片、篡改信息)。
- 凭证无法管控:账号密码一旦提供给 A,用户无法单方面收回权限,只能通过修改密码,操作繁琐且影响自身使用。
这种情况就是,直接提供凭证的方案的不可解决的安全与信任漏洞
OAuth2.0 通过重构「用户 - 第三方应用 - 资源平台」的交互模型,从根源上规避上述漏洞:
- 隔离核心凭证:用户的账号密码仅在资源平台 B 的鉴权服务器上输入,第三方 A 全程无法接触,彻底杜绝凭证泄露。
- 明确权限授权:在展示了授权信息的时候,用户授权时能清晰看到 A 获得的具体权限范围(如 “仅查看相片,不可修改 / 删除”),避免过度授权。这是在告诉用户,如果你授权给 A,那么,A 将获得访问你这些资源的权限
- 临时有限凭证: 如果用户同意授权并且认证通过,那么,接下来鉴权服务器会通知 A,并给 A 发送一个访问令牌,此时注意,A 获得的是「访问令牌(access token)」,而非永久最高权限的账号密码。令牌有明确有效期,且权限被严格限制在用户授权的范围内。有了这个访问令牌,A 就可以拿着它去找资源服务器要资源了。
- 双向信任保障:B 无需绝对信任 A,仅通过鉴权服务器验证 access token 令牌的合法性;用户无需担心凭证被滥用,可掌控授权范围和有效期。
首先我们都知道,账号密码是一切,有了账号密码就几乎可以做任何事情(甚至改掉原密码)。而 access token 是有限制范围的。每个 access token 都有一个 scope,也就是允许执行哪些操作。而且 access token 是有有效期的,就算 access token 被窃取,也不能一直用。这就是为什么需要 OAuth2 协议
具体来说,Oauth2.0 的交互模型的核心是这个样子的:
那么重点来了,这种情况看起来也比较容易自己实现啊,为什么必须用 OAuth2.0 而非简单优化原方案
即使对原接口做 “加密传输密码”“定期更换密码” 等优化,也无法解决核心问题:
- 优化方案仍需 A 接触账号密码,只是降低泄露概率,无法从根本上消除用户和 B 的信任顾虑。
- 优化方案无法实现 “权限精细化管控” 和 “权限随时回收”,一旦凭证泄露,风险依然是全面的。
- OAuth2.0 是行业公认的标准化解决方案,定义了清晰的角色(资源服务器、鉴权服务器)和流程,确保不同平台对接时的安全性和兼容性,避免自定义方案的潜在漏洞。
什么是OAuth2 协议
OAuth2.0 是一套标准化的授权协议,核心是让第三方应用在不获取用户核心凭证(账号密码) 的前提下,安全获取用户在另一平台(资源拥有方)的受限资源,同时明确授权范围和有效期。
简单来说就是当第三方应用需要用户保存在其他应用上的资源时,比如一些网站的第三方登录功能,需要获取用户在其他应用上的用户名和头像等信息,这时通过OAuth开放协议以一种安全的方式授权第三方应用去获取这些资源。
要理解协议,先理清各方职责,用之前 A(第三方应用)、B(相片存储平台)、用户的例子对应:
- 资源所有者:用户本人,拥有 B 平台上的相片资源,有权决定是否授权 A 访问。
- 客户端:第三方应用(A),需要访问用户在 B 上的资源(如展示用户相片)。
- 资源服务器:存储用户资源的服务器(B
的相片存储服务器),提供获取资源的接口(如
/photos),仅接受合法授权请求。 - 授权服务器:由 B 掌控的服务器,负责验证用户身份、处理授权请求,最终发放 “合法访问凭证”(访问令牌)。
注:实际场景中,授权服务器和资源服务器可由同一平台(如 B)部署,无需物理分离,但职责必须明确。
而 OAuth2.0 协议的核心是用「访问令牌」替代「账号密码」,并通过规则解决安全问题:
首先,第三方应用(A)永远拿不到用户在 B 的账号密码,只能获得授权服务器发放的「访问令牌(access token)」,这就把账号密码这个必要的核心凭证替代了,而且令牌有过期时间(如 2 小时),即使泄露,攻击者也只能在有效期内有限使用,风险可控。
而且 Token 令牌有明确的「授权范围(scope)」,比如仅允许 “查看相片”,无法执行 “删除相片”“修改用户信息” 等超出授权的操作。这就实现了一定程度的权限控制,两边业务不受影响。这样,就还会有一个好处,就是授权可以被追溯,用户能在 B 平台查看 “哪些应用获得了授权”,并随时撤销授权(无需修改密码),主动权在用户手中。
Access Token 与 Refresh Token
Access Token是客户端访问资源服务器的令牌。通过这个令牌,客户端可以访问第三方应用上受保护的资源。但是Access Token有效期一般较短(这可以降低Acces Token泄漏而带来的风险),当Access Token过期时用户就需要频繁的授权客户端访问资源以刷新令牌,这非常影响用户体验,因此引入Refresh Token来获取新的Access Token。
下面看看OAuth2.0的基本流程。
- 首先,Authorization Grant,也就是授权请求
- 客户端(Client A)向授权服务器(B 的鉴权服务器)发起授权请求,核心是请求用户的授权许可。
- 例如我们上面说的,用户在 A 网站点击 “希望用 B 账号授权查看相片”,A 就会向 B 的授权服务器发送这个请求。
- 然后,Access Token + Refresh Token,也就是发放了令牌
- 授权服务器(B)验证用户身份(比如用户在 B
的鉴权页面输入账号密码并同意授权)后,向客户端(A)发放两个关键凭证:
- Access Token(访问令牌):用于临时访问资源的 “通行证”,有有效期,权限范围由用户授权决定(比如仅允许 “查看相片”)。
- Refresh Token(刷新令牌):用于在 Access Token 过期后,无需用户再次授权,直接向授权服务器申请新的 Access Token。那么这个Token就是Refresh Token,这个 Token 的有效期一般比较长。
- 授权服务器(B)验证用户身份(比如用户在 B
的鉴权页面输入账号密码并同意授权)后,向客户端(A)发放两个关键凭证:
- 然后,Client 拿着 Access Token 去客户端请求资源
- 客户端(A)拿着刚拿到的 Access Token,向资源服务器(B 的相片存储服务器)发起请求,要求获取用户的受保护资源(比如用户的相片)。
- Protected Resource,资源服务器返回资源
- 资源服务器(B)验证 Access Token 的合法性(比如检查令牌是否过期、权限是否匹配),如果合法,就将受保护资源(用户相片)返回给客户端(A)。
- 5-6需要合一起说,Invalid Token Error(令牌失效)
- 如果 Access Token 过期或无效,资源服务器(B)会向客户端(A)返回 “无效令牌错误”,提示客户端需要更新令牌。
- 步骤7 Refresh Token 就是用刷新令牌换全新访问令牌
- 客户端(A)拿着 Refresh Token 向授权服务器(B)发起请求,申请新的 Access Token。
- 之后,New Access Token,获取到了新访问令牌
- 授权服务器(B)验证 Refresh Token 合法后,向客户端(A)发放新的 Access Token。客户端可以拿着这个新令牌,回到步骤 3 继续请求资源
核心正式我们上面所说,客户端(A)永远拿不到用户在 B 的账号密码,只用临时、受限的 Access Token 访问资源。
而 Refresh Token 让用户无需频繁重新授权,Access Token 过期后自动用刷新令牌续期,不影响用户使用。这就很好了
4种授权类型
为了获得访问令牌(Access Token),客户端需要先从资源所有者(用户)那里获得授权。授权是以授权许可(Grant Type)的形式来表示的。OAuth定义了四种授权类型:
授权码模式(Authorization Code Grant)
它是 OAuth2.0 中最安全、最常用的授权模式,适用于有后端的第三方应用(如 Web 网站、手机 App 后端),核心是通过 “授权码” 作为中间凭证,避免直接暴露访问令牌,进一步降低安全风险。
授权码模式核心就是这样
- 步骤 1:用户访问第三方应用的资源需求
- 用户在 第三方应用(Client)中触发资源访问需求。
- 步骤 2:第三方应用向授权服务器请求 “授权码”
- 第三方应用向授权服务器发送请求,携带自身的
Client_id(相当于第三方应用在授权服务器的 “身份标识”,用于证明自己是合法应用),目的是获取授权码。
- 第三方应用向授权服务器发送请求,携带自身的
- 步骤 3:授权服务器向用户展示 “授权确认界面”
- 授权服务器向 用户(资源所有者)展示授权确认页面,明确告知用户:“第三方应用需要访问你哪些资源(如查看相片)”,请用户确认是否授权。
- 步骤 4:用户确认授权并同意权限范围
- 用户在授权页面上明确同意授权,并确认具体的权限范围(比如仅允许 “查看相片”,不允许 “删除 / 修改”)。
- 步骤 5:授权服务器返回 “授权码” 给第三方应用
- 用户确认授权后,授权服务器生成一个短期有效的授权码,并将其返回给第三方应用。
- 步骤 6:第三方应用用 “授权码 + Client_id” 请求 “访问令牌”
- 第三方应用拿着授权码和
Client_id,向授权服务器发起请求,目的是获取真正用于访问资源的Access Token(访问令牌) 和 Refresh Token(刷新令牌)。 - 注意,这一步是 “后端对后端” 的交互,用户无感知,进一步保障安全。
- 第三方应用拿着授权码和
- 步骤 7:授权服务器返回 “访问令牌 + 刷新令牌”,授权码失效
- 授权服务器验证授权码和 Client_id 合法后,发放 Access Token(用于临时访问资源)和 Refresh Token(用于 Access Token 过期后刷新),同时授权码立即失效(避免被重复利用,进一步提升安全)。
- 步骤 8:第三方应用用 “访问令牌” 请求资源
- 第三方应用拿着 Access Token,向资源服务器(B 的相片存储服务器)发起请求,获取用户的受保护资源(比如用户的相片)。
- 步骤9:资源服务器返回资源
- 资源服务器验证 Access Token 合法(如检查是否过期、权限是否匹配)后,将 用户资源(相片) 返回给第三方应用,最终展示给用户。
这种模式使用了“授权码” 作为中间层,授权码是短期、单次有效的,即使被窃取,也无法直接获取访问令牌(还需结合 Client_id 等验证),大幅降低泄露风险。而且获取访问令牌的过程是 “第三方应用后端 → 授权服务器后端” 的交互,用户和前端全程不接触访问令牌,避免前端泄露。
如果把这种模式类比成 “现实中的授权”:
- 你(用户)想让快递员(第三方应用)进你家(资源服务器)取包裹(资源),但不想给快递员家门钥匙(账号密码)。
- 你先去物业(授权服务器)开一张 “临时授权单(授权码)”,快递员拿着这张授权单和自己的 “员工证(Client_id)” 去物业换一张 “临时门禁卡(Access Token)”,用门禁卡进门取包裹,门禁卡过期后,再用 “续期凭证(Refresh Token)” 换新房卡 —— 全程你没给过钥匙,却安全完成了授权~
隐式授权(Implicit Grant)
它是一种简化版授权模式,适用于无后端的纯前端应用(如单页 Web 应用、手机端纯前端 H5 页面)。核心是跳过 “授权码” 环节,直接在前端获取访问令牌,牺牲了部分安全性以换取流程简化。
我们用 “用户 - 纯前端应用(Client)- 资源服务器 - 授权服务器” 的角色来拆解:
- 用户触发资源访问需求:用户在纯前端应用中(如一个单页网站),点击 “授权访问某平台资源”。
- 前端应用向授权服务器请求授权:前端应用直接向授权服务器发送请求,携带
Client_id(应用标识)和redirect_uri(授权后跳转的前端页面地址)。 - 用户在授权服务器确认授权:授权服务器向用户展示授权确认页,用户同意授权并确认权限范围。
- 授权服务器直接返回 “Access Token” 给前端应用:用户确认后,授权服务器跳过 “授权码” 环节,直接在前端页面的 URL 中返回 Access Token(无 Refresh Token,因为纯前端无法安全存储刷新令牌)。
- 前端应用用 Access Token 请求资源:前端拿着 Access Token 向资源服务器发起请求,获取用户资源。
所以说,隐式授权仅适用于对安全性要求不高的纯前端应用,无法使用 Refresh Token,Access Token 过期后用户需重新授权,Access Token 直接暴露在前端(如浏览器 URL、本地存储),若被窃取,风险相对较高。
可以把隐式授权类比成 “简化版门禁流程”:你(用户)直接给快递员(纯前端应用)一张 “单次临时门禁卡(Access Token)”,他用这张卡直接进门取包裹 —— 流程快,但卡丢了风险也更直接
密码模式(Resource Owner Password Credentials Grant)
密码模式是 OAuth2.0 四种授权模式中安全性较低的一种,它允许第三方应用直接获取用户的账号密码,并以此向授权服务器换取访问令牌。
这种模式仅适用于用户对第三方应用高度信任的场景,且需满足 “第三方应用是资源平台的‘嫡系’或深度合作方” 的条件。一个典型的例子是同一个企业内部的不同产品要使用本企业的 Oauth2.0 体系。在这种情况下,由于是同个企业,不需要向用户展示“xxx将获取以下权限”等字样并询问用户的授权意向,而只需进行用户的身份认证即可。这个时候,只需要用户输入凭证并直接传递给鉴权服务器进行授权即可。
- 用户向第三方应用提供账号密码的凭证:用户直接在第三方应用中输入自己在资源平台(如某账号体系)的账号和密码。
- 第三方应用向授权服务器请求令牌:第三方应用拿着用户的账号密码,向授权服务器发送请求,同时携带自身的
Client_id(证明应用合法性)。 - 授权服务器验证账号密码并发放令牌:授权服务器验证账号密码合法后,直接返回 Access Token(可能包含 Refresh Token)给第三方应用。
- 第三方应用用令牌请求资源:第三方应用拿着 Access Token 向资源服务器发起请求,获取用户资源。
除非万不得已,否则不推荐。OAuth2.0 官方也强调此模式是 “最后的选择”,仅在其他模式不可行时使用。
可以把它类比成 “把家门钥匙直接给保姆”:你(用户)完全信任保姆(第三方应用),直接把家门钥匙(账号密码)给她,她拿着钥匙(密码)去物业(授权服务器)换一张 “长期门禁卡(Access Token)”,然后自由进出你家(资源服务器)取东西 —— 流程简单,但一旦保姆不可信,风险是毁灭性的。
客户端授权模式(Client Credentials Grant)
客户端授权模式是 OAuth2.0 中针对 “应用自身” 而非 “用户个体”*的授权模式,核心是让第三方应用以 “自己的身份” 获取访问令牌,用于访问*与用户无关的平台级资源(如公共 API、应用自身的配置信息等)。
简单来说就是客户端(Client)通过Client_id和Client_secret去授权服务器请求Token,授权服务器认证Client_id和Client_secret是否正确,若正确则发放Token给客户端(Client)。最后客户端通过AccessToken请求资源。
- 客户端提供自身身份凭证:第三方应用(客户端)向授权服务器发送请求,携带自己的
Client_id(应用身份标识)和Client_secret(应用的 “密钥”,用于证明自己是合法且可信的应用)。 - 授权服务器验证应用身份:授权服务器验证
Client_id和Client_secret是否合法,确认是可信应用后,发放 Access Token(可能包含 Refresh Token)给客户端。 - 客户端用令牌请求资源:客户端拿着 Access Token 向资源服务器发起请求,获取与 “应用自身” 相关的资源(而非用户个人资源)。
首先这个整个的流程不需要用户介入,因为它授权的是 “应用本身” 的权限,而非用户个体的资源。
那么获取的 Access Token 仅能访问 “与用户无关的平台级资源”,最经典的就是天气 API 服务商向新闻 App 开放 “公共天气数据” 的访问权限,或者腾讯云服务平台向第三方运维工具宝塔面板开放 “服务器状态查询” 的 API 权限。
那么它的安全是依赖于应用的密钥的,Client_secret
是应用的核心密钥,必须在客户端后端安全存储(如服务器环境),若泄露,第三方可伪装成该应用获取权限。
可以把它类比成 “公司资质授权”:一家企业(第三方应用)拿着自己的 “营业执照(Client_id)” 和 “公章(Client_secret)”,去行业协会(授权服务器)申请 “行业数据查询许可(Access Token)”,拿到许可后,企业可以查询行业公共数据(资源服务器)—— 全程不需要员工(用户)参与,因为授权的是 “公司” 而非 “个人” 的权限。
这种模式是 OAuth2.0 中专门为 “应用间 API 对接、公共资源访问” 设计的授权方案,和其他面向用户个体的模式形成了互补







