对OAuth2.0协议的理解和测试demo

1. 什么是OAuth

OAuth(开放授权)是一个开放标准,允许用户授权第三方网站访问他们存储在另外的服务提供者上的信息,而不需要将用户名和密码提供给第三方网站或分享他们数据的所有内容。

OAuth允许用户提供一个令牌,而不是用户名和密码来访问他们存放在特定服务提供者的数据。每一个令牌授权一个特定的网站(例如,视频编辑网站)在特定的时段(例如,接下来的2小时内)内访问特定的资源(例如仅仅是某一相册中的视频)。这样,OAuth让用户可以授权第三方网站访问他们存储在另外服务提供者的某些特定信息,而非所有内容。

2. OAuth中的术语介绍

角色

OAuth定义了四个角色:

  • 资源所有者(用户)
  • 资源服务器
  • 认证服务器(可以是与资源服务器相同的服务器)
  • 客户端(第三方应用)

用户

OAuth 2.0规范将用户称为“资源所有者”。资源所有者是授予其帐户某些部分访问权限的人。在这种情况下,资源可以是数据(照片,文档,联系人),服务(发布博客条目,转移资金)或任何其他需要访问限制的资源。任何想要代表用户行事的系统必须首先获得他们的许可。

资源服务器

资源服务器是包含第三方应用程序正在访问的用户信息的服务器。资源服务器必须能够接受并验证访问令牌,并在用户允许时授予请求。资源服务器不一定需要知道应用程序。

认证服务器

认证服务器,处理用户的授权请求,以及给客户端(第三方用户)授予一个访问令牌(access_token)。因此,认证服务器通常具有两个主URL,一个用于授权请求,一个用于给客户端授予访问令牌。这些通常是这样的:

客户端

客户端是试图代表用户行动或访问用户资源的应用程序。在客户端可以访问用户的帐户之前,需要获得权限。

授权码

授权码是用于和认证服务器交换令牌使用的,在用户同意授权请求后,认证服务器会返回一个授权码给客户端,然后客户端使用授权码和认证服务器交换访问令牌。

访问令牌(access_token)

访问令牌是向资源服务器发出经过身份验证的请求时使用的字符串。字符串本身对使用它的应用程序没有意义,但表示用户已授权第三方应用程序访问其帐户。令牌具有相应的访问持续时间,范围以及服务器所需的其他可能信息。客户端通过使用访问令牌向资源服务器获取指定的信息。

刷新令牌

刷新令牌是一个字符串,用于在访问令牌过期时获取新的访问令牌。并非所有资源服务器都使用刷新令牌。

3. 协议运作流程

下面是OAuth2.0协议的运作流程图,图片来源:OAuth2.0协议草案V21的1.2节

对OAuth2.0协议的理解和测试demo

上图描述了四个角色之间的互动,主要包括下面几个步骤:

(A) 客户端向用户(资源拥有者)发出授权请求;

(B) 用户同意授权请求;

(C) 客户端向认证服务器进行身份认证,并请求获取访问令牌;

(D) 认证服务器对客户端进行身份校验,如果有效,则发放令牌;

(E) 客户使用令牌向资源服务器获取受保护的资源;

(F) 资源服务器验证令牌,如果有效,则同意客户端的资源访问请求

在步骤(B)中,用户要如何接受客户端的授权请求呢?OAuth2.0协议规定了四种授权类型:authorization code(授权码模式), implicit(简化模式), resource owner password credentials(密码模式), and client credentials(客户端模式)。它还提供了一种用于定义其他授权类型的扩展机制。这里我介绍下授权码模式。

4 authorization code(授权码模式)

下面是授权码模式的流程图,图片来源:OAuth2.0协议草案V21的4.1节

对OAuth2.0协议的理解和测试demo

步骤说明:

(A) 客户端向认证服务器发出授权请求,并将用户导向认证服务器,其中 Client Identifier 表示客户端身份标识,Redirection URI 表示重定向uri;

(B) 认证服务器对资源所有者进行身份验证,并确定资源所有者是否授予或拒绝客户端的访问请求;

(C) 假如用户同意授权,那么认证服务器会重定向到(A)中指定的uri,并返回一个code(授权码);

(D) 客户端使用(C)中获取的授权码code向认证服务器交换令牌(token);

(E) 认证服务器对客户端的身份进行校验,比如说判断code是否有效,uri是否匹配等,如果通过则同意发放令牌。

在上面(A)中的 Client IdentifierRedirection URI 是如何获得的呢?这里我们以github为例,简单说明一下

假如说我们要登陆开源中国,在登录界面我们可以看到,它支持通过微信、QQ、github等账号登陆。如果我们选择github账号登陆,那么开源中国就是客户端,github就是认证服务器,同时也是资源服务器。开源中国在使用OAuth2.0协议和github通信前,首先要到github上面注册OAuth Apps,注册需要的信息包括Application name、Homepage URL、Application description和Authorization callback URL,注册成功后,github会提供client_id和client_secret,其中client_id就表示 Client IdentifierRedirection URI 就是注册时填写的Authorization callback URL。

下面是上面这些步骤所需要的参数。

(A)中,客户端申请认证的URI,包含以下参数:

  • response_type:表示授权类型,必选项,此处的值固定为"code"
  • client_id:表示客户端的ID,必选项
  • redirect_uri:表示重定向URI,可选项
  • scope:表示申请的权限范围,可选项
  • state:客户端用于维护请求和回调之间状态的不透明值。推荐使用

客户端可构造一个包含上述参数的uri,将用户导向认证服务器,例如:

GET /authorize?response_type=code&client_id=s6BhdRkqt3&state=xyz &redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb HTTP/1.1

Host: server.example.com

(C)中,服务器回应客户端的URI,包含以下参数:

code:表示授权码,必选项。该码的有效期应该很短,通常设为10分钟,客户端只能使用该码一次,否则会被授权服务器拒绝。该码与客户端ID和重定向URI,是一

一对应关系。

state:如果客户端的请求中包含这个参数,认证服务器的回应也必须一模一样包含这个参数。

一个成功的例子:

HTTP/1.1 302 Found

Location: https://client.example.com/cb?code=SplxlOBeZQQYbYS6WxSbIA&state=xyz

一个失败的例子:

HTTP/1.1 302 Found

Location: https://client.example.com/cb?error=access_denied&state=xyz

(D)中,客户端向认证服务器申请令牌的HTTP请求,包含以下参数:

grant_type:表示使用的授权模式,必选项,此处的值固定为"authorization_code"。

code:表示上一步获得的授权码,必选项。

redirect_uri:表示重定向URI,必选项,且必须与A步骤中的该参数值保持一致。

client_id:表示客户端ID,必选项。

例如:

POST /token HTTP/1.1

Host: server.example.com

Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW

Content-Type: application/x-www-form-urlencoded;charset=UTF-8

grant_type=authorization_code&code=SplxlOBeZQQYbYS6WxSbIA

&redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb

(E)中,认证服务器发送的HTTP回复,包含以下参数:

access_token:表示访问令牌,必选项。

token_type:表示令牌类型,该值大小写不敏感,必选项,可以是bearer类型或mac类型。

expires_in:表示过期时间,单位为秒。如果省略该参数,必须其他方式设置过期时间。

refresh_token:表示更新令牌,用来获取下一次的访问令牌,可选项。

scope:表示权限范围,如果与客户端申请的范围一致,此项可省略。

一个成功的例子如下:

HTTP/1.1 200 OK

Content-Type: application/json;charset=UTF-8

Cache-Control: no-store

Pragma: no-cache

{

"access_token":"2YotnFZFEjr1zCsicMWpAA",

"token_type":"bearer",

}

5. 模拟OAuth工作流程的demo

demo写的很简单,仅仅是为了帮助协议工作流程~

基于OAuth2.0协议,模拟客户端实现,代码下载地址

基于OAuth2.0协议,模拟服务端实现,代码下载地址

基于OAuth2.0协议,实现访问github的客户端,代码下载地址

参考网站:

上一篇:201521123014 《Java程序设计》第6周学习总结


下一篇:函数:atexit