xb18
xb18
文章78
标签0
分类0
OAuth2.0

OAuth2.0

OAuth 即 Open Authorization,是“开放授权”的简写,它是一个关于授权(authorization)的开放网络标准。一句话,OAuth2.0 是一种授权协议。

无论使用哪种三方平台,最重要的一步就是获取三方授权的 token,当然不同的厂商叫法不一样,有的叫 access_token,有的叫 oauth_token,还有的叫 code。关键是拿到这个凭证后,你就有权限继续去三方获取用户的昵称、头像、动态、好友列表之类的信息。当然,权限也是有范围和有效期的。

在整个过程中,用户凭据未向第三方应用暴露,用户授权的是访问令牌(Access Token),它通常有时间限制,并且只允许访问特定范围的资源。OAuth 2.0提供了一种既安全又方便的方式来实现免登,因为用户只需要与他们信任的认证服务器进行凭据交互。

此外,刷新令牌(Refresh Token)可能被认证服务器颁发,用以在访问令牌失效时获取新的访问令牌,而不需要用户重新进行授权,进一步提升了用户体验。

授权流程

在这里插入图片描述

授权方式

一、授权码模式(最安全)

Authorization Code

指的是第三方应用先申请一个授权码,然后再用该码获取令牌。

最常用,安全性最高的流程。适用于有后端的web应用。由前端传送授权码,令牌则是储存在后端,而且所有与资源服务器的通信都在后端完成。这样的前后分离,可以避免令牌client_secret泄露。

/oauth/authorize 前端调用打开登陆地址,例如跳转qq登陆页获取授权

参数名称参数含义是否必须
response_type授权类型,一般为code,其他例如token必须
client_id客户端ID,客户端到资源服务器注册的ID,例如在开放平台注册的appId必须
redirect_uri重定向URI,授权成功后要重定向到的地址可选
scope申请的权限范围,多个逗号隔开,例如头像、昵称等可选
state客户端的当前状态,可以指定任意值,认证服务器会原封不动的返回这个值推荐

/oauth/token 后端调用

client_id表明身份-客户端id
client_secret表明身份-保密参数,因此只能在后端发送请求
grant_type授权方式,默认为AUTHORIZATION_CODE
code授权码
redirect_uri令牌颁布后的回调网址
1
2
3
4
5
6
7
8
9
10
{
"access_token":"ACCESS_TOKEN", # 令牌
"token_type":"bearer",
"expires_in":2592000,
"refresh_token":"REFRESH_TOKEN", # 用于刷新
"scope":"read",
"uid":100101,
"info":{...}
}

二、简化(隐式)模式(纯前端)

对于纯前端应用,允许直接向前端颁发令牌。这种方式没有授权码这个中间步骤,所以称为(授权码)”隐藏式”(implicit)。

A网站提供一个链接,要求用户跳转B网站授权用户数据给A网站

1
https://b.com/oauth/authorize?response_type=token&client_id=CLIENT_ID&redirect_uri=CALLBACK_URL&scope=read

response_type参数为token,表示要求直接返回令牌

用户在B网站登录并且同意授权给A网站,B网站就会跳回redirect_ui并且令牌会通过url传递

1
https://a.com/callback#token=ACCESS_TOKEN 

注意: 令牌的位置是URL锚点(#携带参数),不是查询字符串。是因为OAuth2.0允许跳转网址是HTTP协议,存在“中间人攻击”风险,而浏览器跳转时,锚点不会发送到浏览器,减少了令牌泄露的风险。

缺点:

  1. 令牌是直接传递给前端的,有一定的安全风险,只能用于一些安全性不高的场景。
  2. 令牌的有效期非常短,通常是会话内有效

三、密码式(高度信任应用)

如果你高度信任某个应用,RFC 6749 也允许用户把用户名和密码,直接告诉该应用。该应用就使用你的密码,申请令牌,这种方式称为”密码式”(password)。

A网站要求用户提供B网站的用户名和密码。拿到以后,A直接向B请求令牌

1
2
3
https://oauth.b.com/token?grant_type=password&username=USERNAME&password=PASSWORD&client_id=CLIENT_ID
// grant_type 授权方式 password-表示密码式
// username password 表示B网站的用户名和密码

B验证用户身份无误后,直接给出令牌(无需跳转),令牌会作为HTTP回应在JSON数据里被拿到

1
2
3
4
5
6
7
{
"access_token":"ACCESS_TOKEN", # 令牌
"token_type":"bearer",
"refresh_token":"REFRESH_TOKEN", # 用于刷新
"scope":"read"
}

需要给出用户名和密码,风险很大,只适用于其他授权方式无法采用的情况,并且是用户高度信任的应用。

四、凭证式(命令行应用)

客户端模式(Client Credentials Grant)指客户端以自己的名义,而不是以用户的名义,向”服务提供商”进行授权。

适用于没有前端的命令行应用,即在命令行下请求令牌。一般用来提供给我们完全信任的服务器端服务。

A应用在命令行向B发出请求

1
2
3
4
https://oauth.b.com/token?grant_type=client_credentials&client_id=CLIENT_ID&client_secret=CLIENT_SECRET 

// grant_type 授权方式 client_credentials-表示凭证式
// client_id和client_secret用来让B确认A的身份

B网站通过验证之后,直接返回令牌

{
“access_token”:”ACCESS_TOKEN”, # 令牌
“token_type”:”bearer”,
“refresh_token”:”REFRESH_TOKEN”, # 用于刷新
“scope”:”read”
}

这种方式给出的令牌,是针对第三方应用的,不是针对客户的,所以有可能多个用户共享一个令牌。

令牌的使用

A网站拿到令牌之后,就可以向B网站的API请求数据了。

每个发到API的请求,都必须带有令牌。具体做法是在请求头信息上,带上Authorization字段,令牌就存放在这个字段里面。

1
2
3
curl ‐H "Authorization: Bearer ACCESS_TOKEN" \
"https://api.b.com"

令牌的更新

如果令牌的有效期到了,重走上面的流程体验性不好,所以OAuth2.0允许用户自动更新令牌。

更新方法

B网站颁布令牌的时候,一次性颁布两个令牌

  • 一个用于获取数据
  • 一个用于获取新的令牌refresh token字段

令牌到期前,用户通过refresh token发送一个请求,去更新令牌。

1
https://b.com/oauth/token?grant_type=refresh_token&client_id=CLIENT_ID&client_secret=CLIENT_SECRET&refresh_token=REFRESH_TOKEN 

response

1
2
3
4
5
6
{
"access_token":"ACCESS_TOKEN", # 令牌
"token_type":"bearer",
"refresh_token":"REFRESH_TOKEN", # 用于刷新
"scope":"read"
}
本文作者:xb18
本文链接:https://moelj.com/2024/07/01/OAuth2.0/
版权声明:本文采用 CC BY-NC-SA 3.0 CN 协议进行许可