修正为:
Leapcell:新一代的无服务器平台,专门用于网页托管、异步任务,并且支持Redis
OAuth 2.0 的简单易懂解释OAuth 是一种广泛使用的全球开放网络授权标准,当前版本为 2.0。我们将基于 RFC 6749,简明扼要地解释 OAuth 2.0 的设计理念。
一. 应用场景
为了帮助理解OAuth适用的情境,我们先来看一个假设的例子。假设有一个名为“云照片打印”的网站,能够打印用户存储在谷歌上的照片。如果用户想要使用这项服务,就需要允许“云照片打印”读取他们存储在谷歌上的照片。
这里有一个关键问题:Google 只会在获得用户授权后,才允许“云照片打印”读取这些照片。这样,“云照片打印”怎么才能得到用户的授权呢?
传统做法是由用户提供或分享他们的 Google 用户名和密码给“云端照片打印”,这样“云端照片打印”可以访问用户的照片。然而,这种方法存在很多严重的问题。
- 密码存储的安全风险:为了提供后续服务,"云照片打印"将存储用户的密码,这带来了很大的安全风险。
- 登录方式的安全问题:谷歌只能使用密码登录方式,但简单的密码登录安全性较差。
- 缺乏权限控制:"云照片打印"可以访问用户存储在谷歌上的所有资料,用户无法限制"云照片打印"所获得授权的范围和有效期。
- 撤销权限成本高:用户只能通过更改密码来撤销给予"云照片打印"的权限,这会导致所有其他已授权的第三方应用失效。
- 数据泄露风险高:一旦一个第三方应用被破解,就会导致用户的密码和受密码保护的所有数据泄露。
为了解决这些问题,OAuth 也因此诞生了。
2. 名词解释在我们详细了解OAuth 2.0之前,首先需要理解几个专用名词。理解它们对于理解相关图表非常重要。
- 第三方应用(Third-party Application):本文中也称为“客户端”,例如在上一节的例子中提到的“云照片打印”。
- HTTP服务提供者(HTTP Service Provider):本文中简称为“服务提供商”,例如在上一节的例子中提到的Google。
- 资源拥有者(Resource Owner):本文中也称为“用户”。
- 用户代理(User Agent):在本文中指的是浏览器。
- 认证服务器(Authorization Server):即服务提供商用来处理认证的专用服务器。
- 资源服务器(Resource Server):即服务提供商存储用户生成的资源的服务器。它可以与认证服务器是同一台服务器,也可以是不同的服务器。
理解了上述名词之后,理解OAuth的作用也就变得容易了,即让“客户端”能够安全且可控地从“用户”那里获取授权,然后就能与“服务提供商”进行交互了。
III. OAuth概念OAuth 在“客户端”和“服务提供商”之间建立了一个授权层。“客户端”无法直接登录到“服务提供商”,而是登录到授权层,以便将用户与客户端区分开来。客户端用来登录授权层的令牌不同于用户的密码,用户在登录时还可以指定授权层令牌的有效期和权限范围。
在“客户端”登录到授权层后,“服务提供者”将会根据令牌的有效权限范围,向“客户端”展示用户的存储材料。
IV. 操作过程OAuth 2.0的操作过程如下图,摘录自RFC 6749:
- (A) :用户打开客户端时,客户端向用户请求授权。
- (B) :用户同意给客户端授权。
- (C) :客户端利用刚才获得的授权向认证服务器申请令牌。
- (D) :认证服务器确认客户端身份无误后,同意发放令牌。
- (E) :客户端用令牌向资源服务器申请资源。
- (F) :资源服务器确认令牌无误后,同意向客户端提供资源。
在这六个步骤中,步骤B尤为关键,即用户如何给客户端授权。有了这个授权,客户端就能拿到token,再用token去获取资源。接下来我会一一解释客户端获取授权的四种方式。
客户端授权模式客户端必须在获得用户授权(授权码)后才能获取访问令牌(access token)。OAuth 2.0 规定了以下四种授权方式:
- 授权码模式
- 隐式模式
- 资源所有者密码模式
- 客户端凭证模式
授权码模式(授权码)是功能最全面、流程最严谨的授权方式之一。其特点是通过客户端后台与服务商的认证服务器进行后台交互。具体流程如下:
- (A) : 用户访问客户端,客户端将用户重定向到认证服务器。
- (B) : 用户决定是否允许客户端访问。
- (C) : 如果用户同意授权,认证服务器将用户重定向到客户端预先指定的“重定向URI”(redirect URI),同时附带一个授权码。
- (D) : 客户端接收到授权码,附带之前的“重定向URI”,并向认证服务器申请令牌。这一步在客户端后台自动完成,用户不会看到。
- (E) : 认证服务器检查授权码和重定向URI。如果一切正常,它将访问令牌(access token)和刷新令牌(refresh token)发送给客户端。
以下是所需参数,用于上述步骤:
-
步骤A:客户端申请认证的URI包含以下参数:
-
response_type:表示授权类型,是一个必填参数,值固定为“code”。
-
client_id:表示客户端的ID,是一个必填参数。
-
redirect_uri:表示重定向的URI,是一个可选的。
-
scope:表示请求的权限范围,是一个可选的。
- state:表示客户端当前状态,可以指定任意值。认证服务器会原封不动地返回这个值。
比如说:
GET /authorize?response_type=code&client_id=s6BhdRkqt3&state=xyz&redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb HTTP/1.1
Host: server.leapcell.io
进入全屏,退出全屏
-
步骤 C :服务器响应客户端时,URI 包含以下参数:
-
code :表示授权码,这是一个必填参数。此代码的有效期非常短,一般设定为 10 分钟,客户端只能使用一次此代码,否则会被授权服务器拒绝。此代码与客户端 ID 和重定向 URI 一一对应关系。
- state :如果客户端请求中包含此参数,认证服务器也必须在响应中包含同样的参数。
例如:
HTTP/1.1 302 Found
Location: https://client.example.com/cb?code=SplxlqweqwWxSbIA&state=xyz
点击切换到全屏,点击切换出全屏
-
步骤 D:客户端向认证服务器发起的用于申请 token 的 HTTP 请求包含以下参数:
-
grant_type :表示授权模式,为必填项,值固定为 "authorization_code"。
-
code :上一步获取的授权码,为必填项。
-
redirect_uri :表示重定向 URI,为必填项,必须与步骤 A 中相同的参数值保持一致。
- client_id :表示客户端的 ID,为必填项。
比如说:
POST /token HTTP/1.1
Host: server.leapcell.io
Authorization: Basic czZCaGRrwrqw0M2JW
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code&code=SplxlOBeZQQYbYS6WxSbIA&redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb
全屏显示,退出全屏
-
步骤 E :认证服务器返回的 HTTP 响应包含以下参数:
-
access_token :表示访问令牌,这是必需的参数。
-
token_type :表示令牌类型。此值不区分大小写,这是必需的参数。它可以是 bearer 类型或 mac 类型。
-
expires_in :表示过期时间(以秒为单位)。如果缺少此参数,则必须通过其他方式设置过期时间。
-
refresh_token :表示刷新令牌,用于获取下一个访问令牌,是可选的参数。
- scope :表示权限范围。如果与客户端请求的一致,可以省略。
比如说:
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8 // 内容类型: application/json;charset=UTF-8
Cache-Control: no-store // 缓存控制: 不存储
Pragma: no-cache // Pragma: 不缓存
{
"access_token":"2YotnFqwrwqrqwCsicMWpAA" // 访问令牌: 2YotnFqwrwqrqwCsicMWpAA
"token_type":"example",
"expires_in":3600 // 有效时间: 3600秒
"refresh_token":"tGzv3JOqweqweTlKWIA" // 刷新令牌: tGzv3JOqweqweTlKWIA
"example_parameter":"example_value" // 示例参数: 示例值
}
进入全屏,退出全屏
从上面的代码可以看出,相关参数通过JSON格式(Content-Type: application/json)发送,并且在HTTP头部信息中明确禁止了缓存。
VII. 简易模式简化模式(隐式授予类型)不需要经过第三方应用的服务器,而是直接在浏览器中从认证服务器申请令牌,跳过了“授权码”这一步,因此得名。所有步骤都在浏览器中完成,令牌在浏览器中对用户可见,客户端不需要进行身份验证。具体的操作步骤如下:
- (A):客户端会引导用户前往认证服务器进行验证。
- (B):用户选择是否同意客户端的请求。
- (C):如果用户同意了,认证服务器将用户重定向到客户端指定的“重定向URI”,并将访问令牌(access token)包含在URI的Hash部分。
- (D):浏览器向资源服务器发出请求,不过请求中不包含之前的Hash值。
- (E):资源服务器返回一个网页,该网页上的代码可以从Hash值中提取令牌。
- (F):浏览器执行获取的代码,从而提取令牌。
- (G):浏览器将令牌传递给客户端。
下面列出的是做这些步骤所需要的一些参数:
-
步骤A:客户端发送的HTTP请求包含以下参数:
-
response_type:表示授权的类型,此处值固定为"token",为必填参数。
-
client_id:表示客户端的ID,为必填参数。
-
redirect_uri:表示重定向的URI,为可选参数。
-
scope:表示权限的范围,为可选参数。
- state:表示客户端当前状态,可以是任意值。认证服务器会原封不动地返回这个值。
例如:
GET /authorize?response_type=token&client_id=s6BhdRkqt3&state=xyz&redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb HTTP/1.1
Host: server.leapcell.io
全屏模式, 退出
-
步骤 C:认证服务器回应客户端的 URI 包含以下参数:
-
access_token:表示访问令牌,这是一个必须的参数。
-
token_type:表示令牌类型。该值不区分大小写,是一个必须的参数。
-
expires_in:表示过期时间,以秒为单位。如果省略此参数,则过期时间必须通过其他方式设置。
-
scope:表示权限范围。如果与客户端请求的权限范围相同,则此项目可省略。
- state:如果客户端请求中包含此参数,则认证服务器的响应也必须包含同样的参数。
比如说:
HTTP/1.1 302 Found(表示请求的资源已被临时移动到新的 URI)
Location: http://example.com/cb#access_token=2YotnFZFEjr1zCsicMWpAA&state=xyz&token_type=example&expires_in=3600(位置)
# access_token=2YotnFZFEjr1zCsicMWpAA(访问令牌)
# state=xyz(状态参数)
# token_type=example(令牌类型)
# expires_in=3600(过期时间,以秒为单位)
点击全屏显示,再点击退出全屏
在上述示例中,认证服务器利用HTTP头信息中的Location字段来指定浏览器重定向到的URL。请注意,此URL中的Hash部分包含令牌。根据步骤D,浏览器将在下一步访问Location指定的URL,但浏览器不会发送该URL中的Hash部分。在下一步E中,服务提供商的资源服务器发送的代码将从Hash部分中提取令牌。
VIII. 密码方式(Password方式)在密码模式(资源所有者密码凭证模式)中,用户将自己的用户名和密码提供给客户端,客户端使用这些信息向“服务提供商”请求授权。在这种模式下,用户必须向客户端提供密码,但客户端不能存储密码。这通常在用户对客户端高度信任的情况下,例如客户端是操作系统的一部分或由知名公司生产。只有在其他授权模式不可用时,认证服务器才会考虑使用这种模式。接下来让我们看看具体步骤:
- (A):用户向客户端提供用户名和密码。
- (B):客户端向认证服务器发送用户名和密码,并请求令牌。
- (C):认证服务器确认一切正常后,向客户端提供访问令牌。
在步骤 B 中,客户端发送的 HTTP (超文本传输协议) 请求包含了以下参数:等等。
- grant_type : 表示授权类型,这里的值固定为 "password",为必填参数。
- username : 表示用户名,为必填参数。
- password : 表示密码,为必填参数。
- scope : 表示权限范围,为可选参数。
比如说,
POST /token HTTP/1.1
Host: server.leapcell.io
Authorization: Basic czZCaGRSa3F0gertetewrmF0M2JW
Content-Type: application/x-www-form-urlencoded
grant_type=password&username=johndoe&password=A3ddj3w
切换到全屏 退出全屏
在步骤 C 里,认证服务器给客户端发了一个访问令牌,比如:
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache
{
"access_token":"2YotnFZqweqwreqwrpAA",
"token_type":"example",
"expires_in":3600,
"refresh_token":"tGzv3rewrewrtr2TlKWIA",
"example_parameter":"example_value"
}
进入全屏 退出全屏
上述代码中各个参数的意义可以参考《授权码模式》部分。在整个流程中,客户端程序不能保存用户的密码。
第九. 客户模式客户端凭证模式意味着客户端直接用自己的名义,而不是用户的名义,对服务提供方进行认证。严格来说,客户端凭证模式不属于OAuth框架需要解决的问题。在这种模式下,用户直接在客户端注册,客户端以自己的名义向服务商请求服务。实际上,这里没有涉及授权问题。具体步骤如下:
- (A):客户端使用认证服务器验证身份并请求令牌。
- (B):认证服务器验证通过后,向客户端提供令牌。
在步骤 A 中,客户端发送的 HTTP 请求中包含以下参数:
- grant_type : 表示授权类型,此处的值必须是“client_credentials”,是必填项。
- scope : 表示权限范围的参数,是可选项。
比如说:
这是一个向服务器发送客户端凭证请求令牌的POST请求。
POST /token HTTP/1.1
Host: server.leapcell.io
Authorization: Basic czZCaGRSqeqwewqmQmF0M2JW
Content-Type: application/x-www-form-urlencoded
grant_type=client_credentials
切换到全屏 退出全屏
认证服务器必须通过某种方法验证用户身份。
例如,在步骤 B 里,认证服务器会向客户端发送一个访问令牌:
# 下面是一个HTTP响应示例
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache
{
"access_token":"2Yotnqweqwe1zCsicMWpAA",
"token类型":"example",
"expires_in":3600,
"示例参数":"example_value"
}
点击全屏 点击退出全屏
上述代码中各个参数的意义请参考“授权模式部分(章节)”。
更新令牌(Token)如果用户访问时客户端的“访问令牌”已过期,则需要使用“刷新 token”申请新的访问令牌。用于更新令牌的 HTTP 请求包含以下参数:具体来说,这些参数包括。
- grant_type : 表示授权模式,这里的值必须是 "refresh_token",为必填参数。
- refresh_token : 表示之前获得的刷新令牌,为必填参数。
- scope : 表示请求的授权范围,不能超过之前申请的范围。如果省略此参数,默认与之前相同。
比如说:
POST /token HTTP/1.1 (HTTP请求方法,用于发送数据到服务器)
Host: server.example.com (主机名,指定服务器地址)
Authorization: Basic czZCaGRSa3F0MzqeqweqwmF0M2JW (授权信息,用于身份验证)
Content-Type: application/x-www-form-urlencoded (内容类型,指定数据格式)
grant_type=refresh_token&refresh_token=tGzv3JOkF0XG5Qx2TlKWIA (请求参数,包含刷新令牌)
点击全屏切换(进入或退出)
Leapcell: 全新无服务器平台,适用于网站托管、异步任务处理和 Redis,点击了解更多最后,我推荐的最佳部署平台是Leapcell,我觉得Leapcell就挺好的。
点击这里: https://leapcell.io/?lc_t=d_oauth
1. 支持多种语言
- 可用 JavaScript、Python、Go 或 Rust 来开发。
2. 您可以免费无限部署项目
- 只按使用付费 — 不用不计费,就这么简单。
3. 超高的性价比
- 按需付费,无闲置时间费用。
- 示例:$25可以支持6.94M请求,平均响应时间为60毫秒。
4. 精简的开发者体验
- 直观的用户界面,轻松完成设置。
- 全自动的CI/CD流水线和GitOps集成。
- 实时指标和日志,提供实用的洞察。
5. 轻松可扩展性和高性能表现
- 自动扩展轻松应对高并发。
- 零运营负担 — 只需专注于构建。
更多详情请查看这里!
Leapcell 推特: https://x.com/LeapcellHQ