OAuth 2.0概念
最近在开发鉴权功能,类似下面的截图(apifox系统的截图),开发到OAuth 2.0方式的时候,遇到一点麻烦,于是简单的梳理了一下。下面用生动的例子讲解一下OAuth 2.0。

角色设定:
- 你(勇敢的冒险者): 你拥有一些珍贵的魔法卷轴和神器,存放在你的个人宝库中。
- 魔法宠物训练师公会(Client Application): 这是一个想要训练你的魔法宠物(比如小火龙、独角兽)的公会,他们需要查阅你的一些魔法卷轴(获取宠物训练知识)和使用你的某些神器(进行特殊训练)。
- 你的守护神龙(Authorization Server & Resource Server): 这条龙负责守护你的宝库。它既负责验证"魔法宠物训练师公会"是否有资格查看你的卷轴和使用你的神器(Authorization Server),也实际保管着这些宝物(Resource Server)。
OAuth 2.0 的流程就像一场精心设计的授权仪式:
-
"魔法宠物训练师公会"的请求信函(Authorization Request):
"魔法宠物训练师公会"想要为你训练宠物,他们会给你送来一封盖有公会印章的正式信函,信中详细说明了他们需要查阅哪些魔法卷轴(例如,《初级火焰掌控》、《独角兽心灵沟通》)以及需要使用哪些神器(例如,"元素共鸣水晶"、"精神力放大镜"),并请求你允许他们访问。
想象一下: 公会就像一群专业的宠物训练师,他们知道如何让你的宠物变得更强大。但他们不能直接闯入你的宝库拿东西,必须先礼貌地请求你的许可。这封信就是他们的正式请求,列出了他们需要的"工具"和"知识"。
-
你前往神龙的居所进行授权(Authorization Grant):
你收到信函后,觉得"魔法宠物训练师公会"看起来很靠谱,也希望他们能帮助你的宠物成长。于是,你亲自前往守护神龙的居所,向它说明了"魔法宠物训练师公会"的请求,并告知神龙你愿意授权他们访问特定的卷轴和神器。
想象一下: 你来到了守护你宝库的强大神龙面前,告诉它:"这些训练师想要借阅这些卷轴和使用这些神器来训练我的宠物,我觉得可以信任他们。"
-
守护神龙授予"授权印记"(Authorization Code):
守护神龙听取了你的意愿后,不会直接把宝库的钥匙交给公会,而是给你一个特殊的、一次性的"授权印记"。这个印记上刻有特定的魔法符文,代表着你已经同意授权"魔法宠物训练师公会"进行访问,但这个印记本身并不能打开宝库。你需要把这个"授权印记"交给公会。
想象一下: 神龙理解了你的意思,于是给你一个闪烁着魔法光芒的"授权印记",告诉你:"把这个交给那些训练师,他们拿着这个才能来我这里换取真正的通行令牌。"
-
"魔法宠物训练师公会"用"授权印记"换取"访问龙鳞"和"刷新龙鳞"(Access Token & Refresh Token Request):
"魔法宠物训练师公会"收到了你给予的"授权印记"后,会带着这个印记,以及他们公会的徽章和秘钥(Client ID 和 Client Secret),来到守护神龙面前,请求兑换能够真正进入宝库的凭证。他们用"授权印记"作为他们获得你授权的证明。守护神龙验证了"授权印记"和公会的身份后,会授予他们一块临时的"访问龙鳞"(Access Token),这块龙鳞在一段时间内具有魔法效力,可以让他们进入宝库并使用被授权的卷轴和神器。
为了方便他们后续的操作,神龙通常还会授予他们一块更珍贵的"刷新龙鳞"(Refresh Token)。当"访问龙鳞"的魔法效力快要消失时,公会可以使用"刷新龙鳞"再次来请求新的"访问龙鳞",而不需要你再次亲自授权。
想象一下: 训练师公会带着"授权印记"和他们的公会信物来到神龙面前,说:"勇敢的冒险者已经同意我们查阅这些卷轴和使用这些神器了,这是他给我们的授权印记。"神龙核实后,给了他们一块闪耀着光芒的"访问龙鳞",这块龙鳞在一段时间内允许他们进入宝库。同时,神龙还给了他们一块更古老的"刷新龙鳞",以便他们在"访问龙鳞"失效后再次申请。
-
"魔法宠物训练师公会"使用"访问龙鳞"进入宝库(Access Protected Resource):
现在,"魔法宠物训练师公会"拥有了"访问龙鳞",他们就可以凭借这块龙鳞进入你的宝库,查阅你授权的魔法卷轴,并使用你授权的神器来训练你的魔法宠物。每次进入宝库或者使用神器时,他们都需要出示这块"访问龙鳞",证明他们获得了你的许可。
想象一下: 训练师们拿着"访问龙鳞",就可以自由出入你的宝库中被授权的区域,学习卷轴上的知识,并使用那些强大的神器来帮助你的宠物提升能力。
-
"访问龙鳞"魔力消退,使用"刷新龙鳞"再次请求(Refresh Token Usage):
当"访问龙鳞"的魔法效力快要消失时,"魔法宠物训练师公会"可以使用"刷新龙鳞"再次来到守护神龙面前,请求一块新的"访问龙鳞",而不需要再次让你亲自跑来授权。守护神龙会验证"刷新龙鳞"的有效性,并颁发新的"访问龙鳞"。
想象一下: 当"访问龙鳞"的光芒逐渐暗淡,快要失效时,训练师们可以使用更珍贵的"刷新龙鳞"再次来到神龙面前,说:"我们的'访问龙鳞'快失效了,这是我们拥有的'长期授权凭证',请允许我们继续工作。"神龙验证后,会再次赐予他们一块新的"访问龙鳞"。
这个奇幻的例子更形象地展示了 OAuth 2.0 的核心流程:
- 授权请求(Request): 表达需求。
- 授权授予(Grant): 冒险者同意。
- 授权码(Code): 临时的授权凭证。
- 访问令牌(Access Token): 短期有效的"通行证"。
- 刷新令牌(Refresh Token): 用于获取新"通行证"的"长期凭证"。
- 资源访问(Resource Access): 使用"通行证"进入宝库。
OAuth 2.0设计
概念讲解完毕,我们继续沿用"勇敢的冒险者"、"魔法宠物训练师公会"和"守护神龙"的奇幻世界设定,这次我们更细致地描述每次请求和响应中可能包含的关键字段。
1. "魔法宠物训练师公会"的请求信函(Authorization Request):
当"魔法宠物训练师公会"想要获得授权时,他们发送给你的"请求信函"中(或者在用户界面上引导你跳转到守护神龙的授权页面时,构建的URL会包含以下关键信息):
response_type
: 明确告知守护神龙他们希望获取的是授权码(通常设置为code
)。client_id
: "魔法宠物训练师公会"在守护神龙那里注册时获得的唯一身份标识,就像他们的公会徽章编号。redirect_uri
: 当守护神龙完成授权后,应该将你(冒险者)导回的"魔法宠物训练师公会"的地址(通常是他们的App或网站的一个特定页面)。这就像告诉神龙,授权完成后把你送回哪个营地。scope
: 请求的权限范围,明确他们需要访问哪些魔法卷轴和神器。例如:read:scrolls:fire
,use:artifact:resonance
. 这就像在信中详细列出他们需要哪些"工具"和"知识"。state
(可选但推荐): 一个由"魔法宠物训练师公会"生成的随机字符串,用于防止跨站请求伪造(CSRF)攻击。这就像信封上的一个特殊防伪标记,用于验证响应的真实性。
你(冒险者)在守护神龙的居所同意授权后,守护神龙会进行处理。
2. 守护神龙授予"授权印记"(Authorization Code):
当你同意授权后,守护神龙会将你重定向回 "魔法宠物训练师公会"提供的 redirect_uri
,并在URL中附带"授权印记"和 state
(如果请求中包含):
code
: 这就是守护神龙颁发的临时"授权印记",是一个一次性的授权码。state
(如果请求中包含): 守护神龙会原样返回 "魔法宠物训练师公会"在请求中发送的state
值,用于让公会验证响应的合法性。
3. "魔法宠物训练师公会"用"授权印记"换取"访问龙鳞"和"刷新龙鳞"(Access Token Request):
"魔法宠物训练师公会"的后台服务器会向守护神龙的授权服务器发送一个 POST 请求,请求体中通常包含以下字段:
grant_type
: 明确告知守护神龙他们正在使用授权码来换取令牌(设置为authorization_code
)。code
: 你(冒险者)给予他们的"授权印记"。redirect_uri
: 必须与在授权请求中使用的redirect_uri
完全一致,用于验证请求的来源。client_id
: "魔法宠物训练师公会"的公会徽章编号。client_secret
: "魔法宠物训练师公会"在守护神龙那里注册时获得的秘密密钥,就像只有公会高层才知道的秘密咒语,用于证明自己的身份。这个密钥需要保密存储,绝不能泄露给冒险者或其他人。
守护神龙验证通过后,会返回包含"访问龙鳞"和"刷新龙鳞"的 JSON 响应:
JSON
json
{
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6Ik1hZ2ljUGV0VHJhaW5lciIsImlhdCI6MTY4MjcwMDAwMH0.signature",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "long_lived_refresh_token_string",
"scope": "read:scrolls:fire use:artifact:resonance"
}
access_token
: 这就是临时的"访问龙鳞",是一个字符串(通常是 JWT 格式),用于访问受保护的资源。token_type
: 令牌类型,通常是Bearer
。expires_in
: 访问令牌的有效期,单位通常是秒(例如,3600 秒 = 1 小时)。refresh_token
: 这就是更珍贵的"刷新龙鳞",用于在访问令牌过期后获取新的访问令牌。scope
: 再次声明了授予的权限范围。
4. "魔法宠物训练师公会"使用"访问龙鳞"进入宝库(Access Protected Resource):
当"魔法宠物训练师公会"想要访问你的魔法卷轴或神器时,他们会在发送给守护神龙的资源服务器的 HTTP 请求头中携带"访问龙鳞":
makefile
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6Ik1hZ2ljUGV0VHJhaW5lciIsImlhdCI6MTY4MjcwMDAwMH0.signature
守护神龙的资源服务器会验证这个"访问龙鳞"的有效性,如果有效,则返回请求的资源(例如,魔法卷轴的内容或允许使用神器的权限)。
5. "访问龙鳞"魔力消退,使用"刷新龙鳞"再次请求(Refresh Token Usage):
当"魔法宠物训练师公会"的"访问龙鳞"快要过期时,他们的后台服务器会向守护神龙的授权服务器发送一个 POST 请求,请求体中包含:
grant_type
: 明确告知守护神龙他们正在使用刷新令牌来获取新的访问令牌(设置为refresh_token
)。refresh_token
: 他们之前获得的"刷新龙鳞"。client_id
: 他们的公会徽章编号。client_secret
: 他们的秘密咒语。
守护神龙验证通过后,会返回一个新的包含"访问龙鳞"(通常也会包含一个新的"刷新龙鳞")的 JSON 响应:
JSON
json
{
"access_token": "new_access_token_string",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "new_refresh_token_string"
}
access_token
: 新的临时"访问龙鳞"。token_type
: 令牌类型。expires_in
: 新访问令牌的有效期。refresh_token
(可选,但常见): 有时刷新令牌也会被轮换,返回一个新的刷新令牌。
通过这个更详细的例子,你应该能更清晰地看到 OAuth 2.0 协议中每次请求和响应中涉及的关键字段,以及它们在整个授权流程中的作用。这就像一场精心设计的魔法仪式,每一步都有特定的咒语和信物(字段)进行沟通和验证。
访问令牌和刷新令牌
"访问龙鳞"(Access Token)和"刷新龙鳞"(Refresh Token)的特性和使用场景。
"访问龙鳞"(Access Token):短暂而强大的魔法通行证
-
特性:
- 魔法效力有限: "访问龙鳞"拥有强大的魔法力量,能够让你("魔法宠物训练师公会")在一段时间内自由出入冒险者(你)的宝库,并使用被授权的魔法卷轴和神器。但是,这种魔法效力是有限的,就像龙的吐息,虽然强大但不能持久。
- 针对特定资源: 一块"访问龙鳞"通常只被授予访问特定范围的资源。例如,一块"访问龙鳞"可能只允许查阅火焰相关的卷轴和使用元素共鸣水晶,而不能查看水系卷轴或使用其他神器。这就像宝库的不同区域需要不同的魔法钥匙。
- 携带方便但需谨慎: "访问龙鳞"通常以一种紧凑的形式(例如,一块刻有符文的玉佩)交给"魔法宠物训练师公会",方便他们在每次访问宝库时出示。但由于其强大的力量,一旦落入坏人之手,可能会被滥用,所以需要谨慎保管。
- 无状态验证: 守护神龙(资源服务器)在验证"访问龙鳞"时,通常不需要每次都去查询自己的数据库。令牌本身可能包含足够的信息(例如,通过 JWT 格式),通过验证其签名即可确认其有效性和所拥有的权限。这就像神龙只需要感知龙鳞上的魔法气息是否正确,而不需要翻阅厚厚的授权记录。
-
使用场景:
- 日常资源访问: "魔法宠物训练师公会"在训练你的魔法宠物时,需要频繁地查阅卷轴和使用神器,他们会每次都出示"访问龙鳞"来获得操作权限。这就像工人每次进入你家的不同房间进行装修时,都需要出示临时的"工作凭证"。
- API 调用授权: 如果"我的云相册"(在这个奇幻的比喻里是守护神龙的宝库)对外提供 API 接口,"照片美化大师"("魔法宠物训练师公会")在调用这些 API 接口时,通常会在请求头中携带"访问龙鳞"作为授权凭证。
"刷新龙鳞"(Refresh Token):续订魔法通行证的古老信物
-
特性:
- 魔法效力持久: "刷新龙鳞"的魔法效力比"访问龙鳞"持久得多,它就像一个古老的信物,代表着守护神龙对"魔法宠物训练师公会"的长期信任(在你授权的前提下)。
- 用于获取新的"访问龙鳞": "刷新龙鳞"本身并不能直接用于访问受保护的资源。它的唯一作用是向守护神龙的授权服务器申请新的、临时的"访问龙鳞"。这就像"长期居住证明"本身不能开门,但可以用来去物业管理处换取新的门禁卡。
- 保管要求更高: 由于"刷新龙鳞"能够续订"访问龙鳞",其重要性更高,因此"魔法宠物训练师公会"需要更加安全地保管它,防止被窃取。一旦泄露,坏人可能会利用它不断地获取新的"访问龙鳞",从而持续访问你的宝库。
- 可能存在使用次数或时间限制: 虽然有效期较长,但为了安全起见,"刷新龙鳞"也可能存在使用次数限制或者一个更长的总有效期。例如,一块"刷新龙鳞"可能只能使用一定次数来获取新的"访问龙鳞",或者在一段时间后彻底失效,需要重新获取。
-
使用场景:
- 静默续订访问令牌: 当"访问龙鳞"即将过期时,"魔法宠物训练师公会"的后台程序可以使用"刷新龙鳞"在用户无感知的情况下向守护神龙请求一个新的"访问龙鳞",从而保证用户操作的连续性,无需重新登录。这就像工人的临时"工作凭证"快过期时,他可以使用"长期居住证明"悄悄地去物业管理处换取新的凭证,而不需要打扰你。
- 长时间保持连接: 对于需要长时间保持与资源服务器连接的应用,"刷新龙鳞"可以确保在"访问龙鳞"过期后能够自动续订,维持连接状态。
为什么需要两者?
- 安全性与便利性的平衡: 使用短期有效的"访问龙鳞"降低了令牌泄露的风险。即使"访问龙鳞"被盗,其有效期有限,造成的损害也较小。而使用长期有效的"刷新龙鳞"则可以在"访问龙鳞"过期后,在用户无需再次交互的情况下获取新的"访问龙鳞",提升了用户体验。
- 权限控制: 可以对"访问龙鳞"的权限范围进行更精细的控制,确保第三方应用只能访问其需要的资源。而"刷新龙鳞"本身不具备访问资源的能力,只是一个"续订凭证"。
- 风险隔离: 即使"刷新龙鳞"被盗,由于它不能直接访问资源,其危害比一个永久有效的、可以直接访问所有资源的令牌要小。同时,可以采取额外的安全措施来保护"刷新龙鳞",例如更严格的存储和使用限制。
总而言之,"访问龙鳞"就像一把临时的、有权限的钥匙,用于日常的资源访问;而"刷新龙鳞"则像一个可以帮你定期更换这把钥匙的长期凭证,在保证安全性的前提下,提供了更好的用户体验。两者协同工作,共同构建了安全且便捷的授权机制。
刷新令牌安全问题
想象一下,这块"刷新龙鳞"不仅仅是一块普通的龙鳞,它蕴含着古老的魔法和守护神龙的某种承诺。
"刷新龙鳞"的奥秘与力量:
- 古老契约的象征: 这块"刷新龙鳞"不仅仅是一个凭证,它更像是你(勇敢的冒险者)与守护神龙之间签订的一个长期契约的象征。当你第一次授权"魔法宠物训练师公会"时,守护神龙不仅给予了他们临时的"访问龙鳞",还赋予了他们这块更珍贵的"刷新龙鳞",代表着在你的允许下,他们可以在未来一段时间内,无需再次惊扰你,也能通过神龙重新获得进入你宝库的许可。
- 维系信任的纽带: "刷新龙鳞"的存在,维系着你、守护神龙和"魔法宠物训练师公会"三者之间的信任关系。你信任神龙能够妥善管理你的授权,神龙信任你最初的授权意愿,而公会则持有这块信物,以便在需要时能够继续获得服务。
- 沉睡的魔法能量: 与活跃的"访问龙鳞"不同,"刷新龙鳞"本身并不直接释放强大的魔法力量来打开宝库。它的力量是沉睡的,只有当"魔法宠物训练师公会"带着它,并以正确的方式(连同他们的公会徽章和秘钥)来到守护神龙面前时,神龙才会感应到这股古老的契约力量,并重新激活,赋予他们新的"访问龙鳞"。
- 谨慎使用的权利: 拥有"刷新龙鳞"就像拥有了一种特殊的权利,可以在"访问龙鳞"失效后再次请求。但这种权利并非没有限制。守护神龙可能会记录下"刷新龙鳞"的使用频率和时间,如果发现异常(例如,在短时间内被多次使用),可能会暂时冻结甚至永久剥夺这块"刷新龙鳞"的力量,以防止滥用。
"刷新龙鳞"的保管与风险:
想象一下,"刷新龙鳞"如果被"哥布林盗贼团"(恶意攻击者)窃取,会发生什么?
- 无需你的许可,持续入侵: 哥布林盗贼团可以拿着这块"刷新龙鳞"偷偷溜到守护神龙那里,谎称自己是"魔法宠物训练师公会",并不断地请求新的"访问龙鳞",从而在一段时间内自由进出你的宝库,偷走你的珍贵卷轴和神器,而你可能毫不知情。这就像小偷拿到了你的长期居住证明,不断地去物业那里领取新的门禁卡。
- 难以追踪的恶意行为: 由于哥布林盗贼团每次都使用新获取的"访问龙鳞"进行非法访问,追踪他们的真实身份和行为会更加困难。你可能只会发现宝库里的东西在不断减少,但很难确定是谁做的。
- 信任体系的破坏: "刷新龙鳞"的泄露不仅会危及你的宝物,也会破坏你对守护神龙和"魔法宠物训练师公会"的信任。你会开始怀疑他们的安全措施是否足够,以及你的授权是否被妥善管理。
守护神龙的应对之策(针对刷新令牌的安全措施):
为了保护"刷新龙鳞"和你的宝库,守护神龙会采取多种魔法和策略:
- 魔法封印与标记: 在颁发"刷新龙鳞"时,神龙会在其上施加特殊的魔法封印和标记,用于识别其合法来源和所属的"魔法宠物训练师公会"。当收到请求时,神龙会仔细检查这些封印和标记是否完好无损。
- 气息追踪与记录: 神龙可能会记录下每次颁发"刷新龙鳞"时的魔法气息和请求者的某些特征(例如,使用的魔法能量波动)。在后续收到使用该"刷新龙鳞"的请求时,神龙会比对这些记录,如果发现气息异常,则会拒绝请求。
- 设置警戒魔法: 在宝库周围设置警戒魔法,如果短时间内出现大量来自同一"刷新龙鳞"的访问请求,就会触发警报,提醒神龙注意可能存在的异常情况。
- 定期更换"刷新龙鳞": 为了进一步提高安全性,守护神龙可能会在一段时间后,要求"魔法宠物训练师公会"重新进行授权流程,颁发一块新的"刷新龙鳞,使旧的失效。这就像定期更换你家的长期居住证明。
- 响应异常撤销魔法: 如果你(冒险者)发现"刷新龙鳞"可能被泄露,你可以告知守护神龙,神龙会立即施展强大的撤销魔法,使该"刷新龙鳞"永久失效。
后面我会实现整个功能。