前言
OAuth
简单理解就是一种授权机制,它是在客户端和资源所有者之间的授权层,用来分离两种不同的角色。在资源所有者同意并向客户端颁发令牌后,客户端携带令牌可以访问资源所有者的资源。
OAuth2.0
是 OAuth
协议的一个版本,有 2.0
版本那就有 1.0
版本,但OAuth1.0
已经不使用了,而且OAuth2.0
不向下兼容。
场景举例
最简单的就是小区单元楼里面的门禁系统,它就是使用OAuth
授权的,朋友过来玩的时候,到楼下有门禁进不来,对于本小区住户来说,可以输入密码进入,因为朋友不是小区住户,直接给他密码不合适,他可以在门禁上面输入我住的住户号,比如 1204
,此时,房间里面的门禁电话就会响,我可以拿起电话,与他通话,确认为我朋友后,按下电话上面的允许
按钮,门禁就会打开,他就可以进来了。
我按下电话上的允许按钮,就相当于给我朋友一个token
,这个token
拥有类似密码
的功能,但也不太相同,token
拥有权限范围,有时效性的,到期自动失效,而且这些属性无法修改。
涉及参数
在讲授权方式前,先了解授权过程中会涉及到的参数:
response_type
:code
表示要求返回授权码,token
表示直接返回令牌client_id
:客户端身份标识client_secret
:客户端密钥redirect_uri
:重定向地址scope
:表示授权的范围,read
只读权限,all
读写权限grant_type
:表示授权的方式,AUTHORIZATION_CODE
(授权码)password
(密码)client_credentials
(凭证式)refresh_token
更新令牌
state
:应用程序传递的一个随机数,用来防止CSRF
攻击。
授权方式
OAuth2.0
的授权简单理解其实就是获取令牌token
的过程,OAuth
协议定义了四种获得令牌的授权方式authorization grant
:
- 授权码(
authorization-code
) - 隐藏式(
implicit
) - 密码式(
password
) - 凭证式(
client credentials
)
不管使用哪一种授权方式,在申请令牌之前,都必须在系统中去申请身份唯一标识,客户端 IDclient ID
和客户端密钥client secret
保证 token
不被恶意使用。
授权码
四种授权中授权码方式
是比较复杂的,安全系数却是最高的,也比较常用。这种方式适用于兼具前后端的Web
项目。
1、用户选择使用微信登录web
,web
会向微信发起授权请求,接下来微信询问用户是否同意授权(手机弹窗确认)。
response_type
为code
要求返回授权码scope
参数表示本次授权范围;redirect_uri
重定向的地址。
https://wx.com/oauth/authorize?
response_type=code&
client_id=CLIENT_ID&
redirect_uri=http://login.web/callback&
scope=read
2、用户同意授权后,微信 根据 redirect_uri
重定向并返回授权码
。
http://login.web/callback?code=AUTHORIZATION_CODE
3、当web
拿到授权码(code
)时,带授权码和密匙等参数向微信申请令牌(access_token
)。
grant_type
表示本次授权为授权码方式authorization_code
client_secret
客户端密匙;code
上一步得到的授权码。
https://wx.com/oauth/token?
client_id=CLIENT_ID&
client_secret=CLIENT_SECRET&
grant_type=authorization_code&
code=AUTHORIZATION_CODE&
redirect_uri=http://login.web/callback
4、最后微信收到请求后向 redirect_uri
地址发送 JSON
数据,其中的access_token
就是令牌。
{
"access_token":"ACCESS_TOKEN",
"token_type":"bearer",
"expires_in":2592000,
"refresh_token":"REFRESH_TOKEN",
"scope":"read",
......
}
隐藏式
如果是纯前端应用,无法使用授权码模式。令牌的申请与存储都需要在前端完成,隐藏式跳过了授权码这一步。前端应用直接获取 token
,response_type
设置为 token
,要求直接access_token
,跳过授权码,微信授权通过后重定向到指定 redirect_uri
。
https://wx.com/oauth/authorize?
response_type=token&
client_id=CLIENT_ID&
redirect_uri=http:/login.web/callback&
scope=read
这种模式安全性相对于授权码
低一些。
密码式
用户在web
页面直接输入自己的微信用户名和密码,web
拿着信息直接去微信申请令牌,请求响应的 JSON
结果中返回 access_token
。grant_type
为 password
表示密码式授权。
https://wx.com/token?
grant_type=password&
username=USERNAME&
password=PASSWORD&
client_id=CLIENT_ID
这种授权方式是非常的危险,相当于把微信密码直接交给了web
系统。如果采取此方式授权的应用一定要高度可信任的。
凭证式
凭证式和密码式比较相似,适用于那些没有前端的命令行应用,可以用最简单的方式获取令牌,在请求响应的 JSON
结果中返回 access_token
。
grant_type
为client_credentials
表示凭证式授权,client_id
和client_secret
用来识别身份。
https://wx.com/token?
grant_type=client_credentials&
client_id=CLIENT_ID&
client_secret=CLIENT_SECRET
令牌使用
拥有令牌就可以调用微信的 API
请求数据了,每个请求微信的请求都必须带上 token
,将 token
放在 http
请求头header
的一个Authorization
里。
令牌刷新
token
是有时效性的,一旦过期就需要重新获取,如果重走一遍授权流程,太过麻烦,一般在颁发令牌 token
时会一次发两个令牌,一个令牌用来请求 API
,另一个负责更新令牌 refresh_token
。
grant_type
为refresh_token
请求为更新令牌,- 参数
refresh_token
是用于更新令牌的令牌。
https://wx.com/oauth/token?
grant_type=refresh_token&
client_id=CLIENT_ID&
client_secret=CLIENT_SECRET&
refresh_token=REFRESH_TOKEN