目录
OAuth2.0解读
前言:参照的是阮一峰老师的博客,基本上是照搬过来的,看别的资料找不到全乎的,OAuth2.0的英文官网文档看不下去,只能是先搬过来了,自己吃透以后再去做实战!
阮一峰老师博客的OAuth2.0
地址: http://www.ruanyifeng.com/blog/2019/04/oauth-grant-types.html
一、含义
OAuth2.0
:引入了一个授权层,用来分离两种不同的角色:客户端、资源所有者。资源所有者同意以后,资源服务器可以向客户端颁发令牌,客户端通过令牌,去请求数据。
OAuth2.0
提供程序机制负责公开受保护的OAuth 2.0
资源。配置涉及建立OAuth2.0
客户端,该客户端可以独立或代表用户访问受保护的资源。提供者通过管理和验证用于访问受保护资源的OAuth2.0
令牌来实现这一点。在适用的情况下,提供商还必须为用户提供一个接口,以确认客户端可以被授予对受保护资源的访问权(即确认页)。
OAuth
的核心就是向第三方应用颁发令牌
二、四种授权流程
OAuth2.0
规定了四获得令牌的流程。根据不同的场景,我们可以选择最适合的一种,向第三方应用颁发令牌:
- 授权码(
authorization-code
) - 隐藏式(
implicit
) - 密码式(
password
) - 客户端凭证(
client credentials
)
注意,不管哪一种授权方式,第三方应用申请令牌之前,都必须到系统备案,说明自己家的身份,然后会拿到两个身份识别码:客户端ID(client ID
)和客户端密码(client secret
)。这是为了防止令牌被滥用,没有备案过的第三方应用,是拿不到令牌的。
2.1 授权码
第三方应用先申请一个授权码(code
),然后再使用该码获取令牌(token
)!
这种方式是最常用的流程,安全性也高,适用于有后端的web
应用。
授权码(code
)通过前端传输,令牌(token
)则是存储在后端,而且所有与资源服务器的通信都在后端完成。
这样前后端分离,可以避免令牌泄露。
第一步
A
网站提供一个链接,用户点击之后跳转到B
网站,授权用户数据给A
网站使用。
https://b.com/oauth/authorize?
response_type=code&
client_id=CLIENT_ID&
redirect_uri=CALLBACK_URL&
scope=read
- response_type 要求返回的数据类型:授权码
code
- client_id 客户端身份
id
【供授权服务器识别】 - redirect_uri 授权成功后重定向地址【
A
网站某个页面】 - scpoe 期望获取的权限范围
第二步
用户跳转到B
网站以后,询问是否同意给予A
网站scope=read
的授权,用户表示同意,这时候B
网站就会跳回到redirect_uri
参数所指定的网址,并且附带一个授权码code
:https://a.com/callback?code=xxx
第三步
A
网站拿到授权码以后,就可以在后端,向B
请求令牌
https://b.com/oauth/token?
client_id=CLIENT_ID&
client_secret=CLIENT_SECRET&
grant_type=authorization_code&
code=AUTHORIZATION_CODE&
redirect_uri=CALLBACK_URL
- client_id 客户端身份
ID
- client_secret 客户端确认身份的密码
- grant_type 授权方式:
AUTHORIZATION_CODE
- code 第二步拿到的授权码
code
- redirect_uri 令牌颁发成功后的回调地址
第四步
B
网站收到请求令牌的请求以后,就会颁发令牌token
,具体做法是向redirect_uri
指定的网址,发送一段json
数据
{
"access_token":"ACCESS_TOKEN",
"token_type":"bearer",
"expires_in":2592000,
"refresh_token":"REFRESH_TOKEN",
"scope":"read",
"uid":100101,
"info":{...}
}
- access_token 令牌
token
【必须】 - token_type
token
类型【必须】 - expire_in 多少秒之后过期【推荐】
- scope 授权范围【可选】
- state 用于保持请求和回调的状态 ,记录用户请求授权页面的位置,可以防止跨站请求伪造
CSRF
攻击,使用条件较为苛刻,且现在很多网站也存在这种漏洞
2.2 隐藏式
有些web
是纯前端应用,没有后端,这时候就不能使用**【授权码】**模式了,需要将令牌token
存储在前端,此时没有【授权码】这个中间步骤。
第一步
A
网站提供一个链接,要求用户跳转到B
网站,授权用户数据给A
网站使用
https://b.com/oauth/authorize?
response_type=token&
client_id=CLIENT_ID&
redirect_uri=CALLBACK_URL&
scope=read
上面的URL
中,response_type
参数为token
,表示要求直接返回令牌
第二步
用户跳转到B
网站,登录后同意授权,这时,B
网站重定向到redirect_uri
指定的网址,并且把令牌token
作为URL
参数 ,传给A
网站
https://a.com/callback#token=ACCESS_TOKEN
上面的URL
中,token
参数就是令牌,A
网站因此直接在前端拿到令牌
这种方式把令牌直接传给前端,是很不安全的。因此,只能用于一些安全要求不高的场景,并且令牌的有效期必须非常短,通常就是会话期间(session)有效,浏览器关掉,令牌就失效了。
2.3 密码式
如果我们高度信任某个应用,OAuth2.0
也允许用户把用户名和密码,直接告诉客户端,该客户端就会使用这个密码申请令牌。
第一步
A
网站要求用户提供 B
网站的用户名和密码。拿到以后,A
就直接向 B
请求令牌
https://oauth.b.com/token?
grant_type=password&
username=USERNAME&
password=PASSWORD&
client_id=CLIENT_ID
上面 URL 中,grant_type
参数是授权方式,这里的password
表示"密码式",username
和password
是 B 的用户名和密码。
第二步
B
网站验证身份通过后,直接给出令牌token
,注意,这个时候是不需要跳转的,而是把令牌放在JSON
数据里面,作为HTTP
回应,A
因此拿到令牌token
。
2.4 凭证式
第一步
A
网站向B
网站发出请求
https://oauth.b.com/token?
grant_type=client_credentials&
client_id=CLIENT_ID&
client_secret=CLIENT_SECRET
上面URL中,grant_type
等于client_credentials
表示采用凭证式授权,client_id
和client_secret
用来让B
确认A
网站的身份
第二步
B
网站对A
网站的身份验证通过后,直接返回令牌token
这种方式给出的令牌,是针对第三方应用的,而不是针对用户的,即可能有多个用户共享一个令牌token
token令牌的使用
1. 请求授权资源时携带令牌
A
网站令牌token
的使用,就可以向B
网站的API
请求数据了。
此时,每个发到API
的请求,都必须带有令牌。
具体的做法就是请求头header
加上Authorization
字段,令牌就存放在这个字段里面
2. 更新令牌
令牌token
的有效期到了,如果让用户重新走一遍上面的流程,再申请一个新的令牌,很可能体验不好,而且也没必要,OAuth2.0
是允许用户自动更新令牌的。
B
颁发令牌的时候,一次颁发两个令牌,一个用于获取数据,另外一个用于获取新的令牌refresh_token
令牌到期前,用户使用refresh_token
发一个请求,去更新令牌。
https://b.com/oauth/token?
grant_type=refresh_token&
client_id=CLIENT_ID&
client_secret=CLIENT_SECRET&
refresh_token=REFRESH_TOKEN
上面URL中,grant_type
参数为refresh_token
表示要求更新令牌,client_id
参数和client_secret
参数用于确认身份。
B
网站验证身份通过后,就会颁发新的令牌。