先贴出我学习的链接,以表尊重,强烈推荐:http://www.ruanyifeng.com/blog/2019/04/oauth_design.html
OAuth是一种授权机制。数据的所有者告诉系统,同意授权第三方应用进入系统,获取数据,系统从而产生的短期令牌,代替密码,给第三方应用使用。
令牌和密码的差异:
①令牌的时间段很短,很快就过期,而且无法自己修改,但是密码不会。
②令牌的权限十分有限,只能做允许的事情。
③资源的所有者可以随时取消令牌的效能。
(泄露令牌与泄露密码的后果是一样的)
令牌授权的4中方式:
(不管哪一种授权方式,第三方应用申请令牌之前,都必须到资源系统备案,说明自己的身份,然后拿到身份识别码,客户端ID(client ID)和客户端密钥(client secret)。反之没有备案的就拿不到令牌)
1.授权码(常用):
适用场景:有后端的web应用
传输方式:授权码通过前端传送,令牌则存储后端,与资源服务器通信也在后端。
详细步骤:(A网站属于第三方应用,B网站属于资源服务器)
①A网站提供链接,点击后跳转到B网站,B网站授权用户数据给A网站使用。
示意链接:
https://b.com/oauth/authorize?
response_type=code& (代表返回授权码)
client_id=CLIENT_ID& (代表A网站)
redirect_uri=CALLBACK_URL& (成功或失败跳转的地方)
scope=read (授予权限的范围)
②在B网站会要求用户登录,同意登录后就会根据redirect_uri跳转指定网站。并且携带着授权码
③A网站拿到授权码后,就可以在后端,向B网站请求令牌。
示意链接:
https://b.com/oauth/token?
client_id=CLIENT_ID& (用来确认A网站身份)
client_secret=CLIENT_SECRET&(用来确认A网站身份,而且参数保密)
grant_type=authorization_code& (代表授权的方式是授权码)
code=AUTHORIZATION_CODE& (授权码)
redirect_uri=CALLBACK_URL (令牌颁发后的回调地址)
④B网站收到请求,颁发令牌,跳转到redirect_uri指定网址,发送json数据。
示意数据:
{
"access_token":"ACCESS_TOKEN", (令牌,A网站在后端拿到了)
"token_type":"bearer",
"expires_in":2592000,
"refresh_token":"REFRESH_TOKEN",
"scope":"read",
"uid":100101,
"info":{...}
}
2.隐藏式:
适用场景:纯前端应用,没有后端,并且安全要求不高的场景
传输方式:直接向前端颁发令牌,没有授权码
详细步骤:
①跟授权码式第一步一致。
②跳转B网站,同意授权后,会根据redirect_uri跳转并且在url上携带令牌传到A网站。
注意:这种方式相对比较不安全,通过url传输令牌,所以令牌的有效期必须非常短,一般是浏览器关掉,令牌就失效
3.密码式:
适用场景:高度信任某个应用(风险大)
详细步骤:
①A网站要求用户提供B网站的账号和密码,拿到后直接申请令牌。。
https://oauth.b.com/token?
grant_type=password& (代表用的是密码式)
username=USERNAME& (账号)
password=PASSWORD& (密码)
client_id=CLIENT_ID (识别A网站)
②B网站验证身份后直接发放令牌,这里没有跳转,而且将令牌存于JSON数据中,作为HTTP回应。
4.凭证式:
适用场景:没有前端的命令行应用
详细步骤:
①A应用在命令行向B应用请求。
https://oauth.b.com/token?
grant_type=client_credentials& (代表使用凭证式)
client_id=CLIENT_ID& (确认A身份)
client_secret=CLIENT_SECRET (确认A身份)
②B应用通过后直接返回令牌
令牌使用:
请求API的时候,都必须带令牌,加上Authorization字段,令牌就存在里面。
更新令牌:
B网站颁发令牌的时候,一次性颁发两个,一个获取数据,一个用于获取新的令牌,令牌到期前,用户用refresh token发送请求,就会更新令牌。
https://b.com/oauth/token?
grant_type=refresh_token& (表示更新令牌)
client_id=CLIENT_ID& (代表A网站身份)
client_secret=CLIENT_SECRET& (代表A网站身份)
refresh_token=REFRESH_TOKEN (用于更新令牌的令牌)