OAuth2.0授权协议
- 用途
通过用户授权,第三方服务访问用户存在其他服务上的资源,而不需用户将用户名密码直接传递的资源服务器的安全控制协议。
传统的认证方式是通过用户/密码方式,认证成功后根据配置的用户权限进行相关资源的访问和操作,这样用户必须在该网站注册才能做其他的事情。现在我们可以看到,很多网站都支持微信、qq登录,这样应用不需要用户单独注册,仅通过与腾讯进行对接,用户通过其在腾讯已有的账号进行认证即可,当然前提是,腾讯开发的权限或用户授权的权限足够,之后应用就可以根据用户的授权记录去腾讯服务器调用数据资源。
参考:
http://www.ruanyifeng.com/blog/2014/05/oauth_2_0.html
https://www.cnblogs.com/gavincoder/p/8999954.html
- 角色
Third-party application:第三方应用程序,用户资源的请求方。
HTTP service:用户资源持有方,服务提供方。
Resource Owner:资源所有者,即"用户"。
User Agent:用户代理,一般指浏览器。
Authorization server:认证服务器,即服务提供商专门用来处理认证的服务器。
Resource server:资源服务器,即服务提供商存放用户生成的资源的服务器。一般与认证服务器为同一台。
- 流程
(A)用户打开客户端以后,获取存储在其他服务上的资源,客户端将用户导向认证界面,要求用户给予授权。
(B)用户同意给予客户端授权。
(C)客户端使用上一步获得的授权,向认证服务器申请令牌。
(D)认证服务器对客户端进行认证以后,确认无误,同意发放令牌。
(E)客户端使用令牌,向资源服务器申请获取资源。
(F)资源服务器确认令牌无误,同意向客户端开放资源。
- 模式
授权码模式(authorization code)
简化模式(implicit)
密码模式(resource owner password credentials)
客户端模式(client credentials)
授权码模式:
(A)用户访问客户端,后者将前者导向认证服务器。
由资源提供方提供具体的认证地址: GET /authorize?response_type=code&client_id=<client_id>&state=<state>&redirect_uri=<redirect_uri>
- response_type:表示授权类型,必选项,此处的值固定为"code"
- client_id:表示客户端的ID,必选项
- redirect_uri:表示重定向URI,可选项
- scope:表示申请的权限范围,可选项
- state:表示客户端的当前状态,可以指定任意值,认证服务器会原封不动地返回这个值。
(B)用户选择是否给予客户端授权。
一般需要用户输入用户名/密码认证,或者通过本地实例直接认证。
(C)假设用户给予授权,认证服务器将用户导向客户端事先指定的"重定向URI"(redirection URI),同时附上一个授权码。
资源提供方在用户认证无误后,会调用A步骤中的<redirect_uri>并附带code、state参数。
- code:表示授权码,必选项。该码的有效期应该很短,通常设为10分钟,客户端只能使用该码一次,否则会被授权服务器拒绝。该码与客户端ID和重定向URI,是一一对应关系。
- state:如果客户端的请求中包含这个参数。
(D)客户端收到授权码,附上早先的"重定向URI",向认证服务器申请令牌。这一步是在客户端的后台的服务器上完成的,对用户不可见。
第三方服务器在后台向资源提供方发送请求,获取令牌,请求地址又提供方定义,携带以下参数。
POST /token grant_type=authorization_code&code=<code>&redirect_uri=<redirect_uri>&client_id=<client_id>
- grant_type:表示使用的授权模式,必选项,此处的值固定为"authorization_code"。
- code:表示上一步获得的授权码,必选项。
- redirect_uri:表示重定向URI,必选项,且必须与A步骤中的该参数值保持一致。
- client_id:表示客户端ID,必选项。
(E)认证服务器核对了授权码和重定向URI,确认无误后,向客户端发送访问令牌(access token)和更新令牌(refresh token)。
认证服务器接收post请求后进行认证,并返回如下内容:
- access_token:表示访问令牌,必选项。
- token_type:表示令牌类型,该值大小写不敏感,必选项,可以是bearer类型或mac类型。
- expires_in:表示过期时间,单位为秒。如果省略该参数,必须其他方式设置过期时间。
- refresh_token:表示更新令牌,用来获取下一次的访问令牌,可选项。
- scope:表示权限范围,如果与客户端申请的范围一致,此项可省略
(F)第三方服务器每次请求携带access_token进行资源访问
简化模式:
授权码模式(authorization code)是功能最完整、流程最严密的授权模式。它的特点就是通过客户端的后台服务器,与"服务提供商"的认证服务器进行互动。
(A)客户端将用户导向认证服务器。
客户端发送请求需要的参数:
- response_type:表示授权类型,此处的值固定为"token",必选项。
- client_id:表示客户端的ID,必选项。
- redirect_uri:表示重定向的URI,可选项。
- scope:表示权限范围,可选项。
- state:表示客户端的当前状态,可以指定任意值,认证服务器会原封不动地返回这个值。
(B)用户决定是否给于客户端授权。
(C)假设用户给予授权,认证服务器将用户导向客户端指定的"重定向URI",并在URI的Hash部分包含了访问令牌。
重定向URI包含如下参数,通过hash方式传递(#):
- access_token:表示访问令牌,必选项。
- token_type:表示令牌类型,该值大小写不敏感,必选项。
- expires_in:表示过期时间,单位为秒。如果省略该参数,必须其他方式设置过期时间。
- scope:表示权限范围,如果与客户端申请的范围一致,此项可省略。
- state:如果客户端的请求中包含这个参数,认证服务器的回应也必须一模一样包含这个参数。
(D)浏览器向资源服务器发出请求,其中不包括上一步收到的Hash值。
(E)资源服务器返回一个网页,其中包含的代码可以获取Hash值中的令牌。
(F)浏览器执行上一步获得的脚本,提取出令牌。
与授权码模式相比,此模式不需要在后台通过授权码获取令牌,而是直接通过前端截取令牌,然后在访问资源时携带。
(G)浏览器将令牌发给客户端。
密码模式:
密码模式(Resource Owner Password Credentials Grant)中,用户向客户端提供自己的用户名和密码。客户端使用这些信息,向"服务商提供商"索要授权。在这种模式中,用户必须把自己的密码给客户端,但是客户端不得储存密码。这通常用在用户对客户端高度信任的情况下,比如客户端是操作系统的一部分,或者由一个著名公司出品。而认证服务器只有在其他授权模式无法执行的情况下,才能考虑使用这种模式。
(A)用户向客户端提供用户名和密码。
(B)客户端将用户名和密码发给认证服务器,向后者请求令牌。
请求需要的参数:
- grant_type:表示授权类型,此处的值固定为"password",必选项。
- username:表示用户名,必选项。
- password:表示用户的密码,必选项。
- scope:表示权限范围,可选项。
(C)认证服务器确认无误后,向客户端提供访问令牌。
返回凭证:
{
"access_token":"2YotnFZFEjr1zCsicMWpAA",
"token_type":"example",
"expires_in":3600,
"refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA",
"example_parameter":"example_value"
}
客户端模式:
客户端模式(Client Credentials Grant)指客户端以自己的名义,而不是以用户的名义,向"服务提供商"进行认证。严格地说,客户端模式并不属于OAuth框架所要解决的问题。在这种模式中,用户直接向客户端注册,客户端以自己的名义要求"服务提供商"提供服务,其实不存在授权问题。
(A)客户端向认证服务器进行身份认证,并要求一个访问令牌。
包含参数:
- granttype:表示授权类型,此处的值固定为"clientcredentials",必选项。
- scope:表示权限范围,可选项。
(B)认证服务器确认无误后,向客户端提供访问令牌。
生成令牌:
{
"access_token":"2YotnFZFEjr1zCsicMWpAA",
"token_type":"example",
"expires_in":3600,
"example_parameter":"example_value"
}
令牌更新:
主要参数:
- granttype:表示使用的授权模式,此处的值固定为"refreshtoken",必选项。
- refresh_token:表示早前收到的更新令牌,必选项。
- scope:表示申请的授权范围,不可以超出上一次申请的范围,如果省略该参数,则表示与上一次一致。
- 示例
以简书调用微博进行授权为示例:
1)进入简书登录界面
2) 点击微博进入授权界面
同时关注地址栏,解码后如下,可见是通过授权码模式进行授权
https://api.weibo.com/oauth2/authorize?client_id=1881139527&redirect_uri=http://www.jianshu.com/users/auth/weibo/callback&response_type=code&state={}
3)微博会向上面的redirect_uri发送请求,同时携带code参数,下面是抓包数据
http://www.jianshu.com/users/auth/weibo/callback?code=xxxx
4)简书获取code,并在后台向微博发送POST请求,其中会携带以下参数:
POST https://api.weibo.com/oauth2/access_token
- client_id:在微博开放平台申请的应用 ID
- client_secret:在微博开放平台申请时提供的APP Secret
- grant_type:需要填写authorization_code
- code:上一步获得的 code
- redirect_uri:回调地址,需要与注册应用里的回调地址以及第一步的 redirect_uri 参数一致
5)微博返回令牌相关的数据,格式如下:
{ "access_token": "ACCESS_TOKEN",//Token 的值 "refresh_token": "REFRESH_TOKEN",//刷新token "expires_in": 3600,//过期时间 "uid":"id"//当前授权用户的UID。 }
6)简书通过access_token就可以访问微博接口,获取根据授权获取数据或进行一些操作
7)简书获取获取用户信息,并在其系统 内部完成认证
8)若令牌过期,则可以通过refresh_tkoen获取新的令牌,如果失败则重新授权
由于以上一些流程是在系统内部完成,同时微博是https请求,所以没有抓取打请求信息,所以没有截图。
转载于:https://my.oschina.net/suspring/blog/3101776