彻底搞明白OAuth2.0
Posted 哇牛笔记
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了彻底搞明白OAuth2.0相关的知识,希望对你有一定的参考价值。
OAuth2.0介绍
传统的c/s认证模型中,客户端如果想要访问服务器上受保护的资源,需要首先获取资源所有者(即用户的)凭证,为了让第三方应用能访问到这些受保护的资源,资源所有者即用户就需要把他们的凭证(一般是用户名和密码)分享给第三方应用,这种方式有以下几个问题和限制:
第三方应用需要存储用户的的凭证如用户名和密码,以供以后再次访问用户资源时使用
服务端需要承担密码认证等一系列密码保护的风险
一旦把用户名密码给了第三方应用,就等于给了第三方应用很大的用户信息访问权限,这样风险很大。如果用户想收回授权,必须修改密码等
OAuth解决了上述一系列问题,OAtuth协议通过引入认证层把第三方应用和用户解耦,第三方应用如果想要访问资源服务器上的用户资源,不再是直接使用用户的用户名和密码,而是使用一套新的信任凭证,在用户允许的情况下,资源服务器给第三方应用发送该凭证
客户端不再是直接使用用户的用户名和密码,而是在用户同意的情况下,由认证服务器给第三方应用(client)发送一个access token, client使用该token可以在一定的时间内访问用户允许的某些资源
角色(roles)
resource owner 指用户
resource server 资源服务器
authorization server 授权服务器
client 客户端,这里指第三方应用
授权服务器与资源服务器通常可以是部署在一起。这两个角色指的是指开放登录服务(即提供用户账号信息)的的服务,如微博 qq 微信 github等
交互流程如下所示:
协议流程说明
A:客户端请求用户的许可,该认证请求可以是直接发送给用户,比如直接是让用户输入用户名密码,也可以是直接跳转到授权服务器(如微博 github等)让用户登录授权服务器上的账号信息
B:客户端得到用户的认证授权。
C:客户端使用授权服务器给的授权凭证去获取access_token(令牌)
D:授权服务器检测授权凭证(授权码)合法就返回令牌
EF:使用令牌请求受保护的用户资源
获取令牌的方式
要想使用支持登录服务的功能,首先需要到支持登录服务的平台(如github 微博 qq 微信等)去注册自己的应用。平台会给第三方应用两个身份识别码:客户端ID 和 客户端密钥串。就是我们常用的clientid 和 client secret
authorization-code(授权码)
授权码方式,是指第三方应用先申请得到一个授权码,然后使用该授权码去获取令牌。这种方式是使用最多也最安全的。授权码通过前端传送,令牌则储存在后端,所有与资源服务器的交互都是在后端完成的。所以这种方式适合于所有具有后端的额应用。并且前后端分离,也能避免令牌的泄漏。
1: 假设第三方应用A使用github的登录功能,首先A网站提供一个链接,用户点击后跳转到github,授权用户的gitub账号数据给A应用使用
https://github.com/oauth2.0/authorize?response_type=code&client_id=client_id&redirect_uri=callback
&scope=read
reponse_type=code 表示要求返回授权码,
client_id 就是我们的应用在github上注册的应用id
redirect_uri: github同意或者拒绝后跳转到的网址
scope=read 授权范围,这里是只读
2:当用户在github上登录并点击同意授权后,就会跳转到redirect_uri指定的网址并返回一个授权码,如下所示
https://a.com/callback?code=Authorizationcode
3:A网站拿到授权码后,就可以在后台像github发起如下请求获取令牌
https://github.com/oauth2.0/token?client_id=client_id&client_secret=client_secret&grant_type=authorization_code&code=
Authorizationcode&redirect_uri=callback
github收到这个获取令牌的请求后,校验通过就会颁发令牌,就是像redirect_uri 指定的网址发送一段json数据。格式如下
{"access_token":"ACCESS_TOKEEN","token_type":"bearer","expires_in":3000,"refresh_token":"REFRESH_TOKEN","scope":"read","uid":2222,"info":{}}
access_token就是令牌。
implicit
适用于没有后端的应用,令牌必须存储在前端。这种认证方式就没有授权码一说了,而是直接获取令牌
1 https://github.com/oauth2.0/authorize?response_type=token&client_id=client_id&redirect_uri=callback&scope=read
reponse_type=token 表示直接获取令牌
2 github直接把令牌返回 跳转到redirecrt_uri中指定的网址。https://a.com/callback#token=ACCESS_TOKN
应用直接在前端链接中拿到令牌
注意这里使用了url的锚点而不是query参数,这是因为OAuth2.0允许跳转网址是http协议的,这样就存在中间人攻击的风险,而浏览器跳转时,锚点是不会发送到服务器的,所以可以减少风险
pasasword
直接使用用户在github上的用户名和密码去拿token
https://github.com/oauth2/token?grant_type=password&username=xxx&password=xx&client_id=clinet_id。此种授权方式不需要跳转,github直接把token放在json数据中作为响应。
client credentials
适用于命令行应用。A应用直接在命令行中请求github。
https://github.com/oatuh2.0/token?grant_type=clienet_credntials&client_id=client_id&client_scret=client_secret
这种方式给的令牌,是针对第三方应用的。即可能多个用户共用一个令牌
令牌的使用方式
在请求header中加上Authorization字段:如下
curl -H “Authorization: Bearer ACCESS_TOKEN” https://api.github.com
OAuth2.0允许用户自动更新令牌,再向第三方应用颁发令牌时,一次性颁发两个,一个用于获取数据,一个用于刷新令牌。令牌到期后,用户可以使用refresh_token发一个请求,格式如下
https://github.com./oauth2.0/token?grant_type=refresh_token&client_id=client_id&client_secret=client_secret&refresh_token=refresh_token
github校验通过后,会颁发新的令牌
以上是关于彻底搞明白OAuth2.0的主要内容,如果未能解决你的问题,请参考以下文章