OAuth 2.0 是一个开放的标准协议,允许应用程序访问其它应用的用户授权的数据。例如:一个游戏可以获取 Facebook 中的用户信息,或者是一个地理位置程序可以获取 Foursquare 的用户信息等。
这儿是一个示例图:
首先用户进入游戏的 web 应用,该应用要求用户通过 Facebook 账户登录,并定向到 Facebook 的登录界面,用户登录 Facebook 后,会重定向到之前的游戏应用。此时该应用就获取到了用户在 Facebook 的用户数据以及授权信息。
OAuth 2.0 既可以用于在某个应用内访问其它应用的用户信息,又可以提供用户授权服务供其它应用调用。
OAuth 2.0 是 OAuth 1.0 的替代,因为 OAuth 1.0 太复杂了,比如 OAuth 1.0 要求使用证书等。OAuth 2.0 更加简单,不要求使用证书,仅使用 SSL/TLS。
这个教程的目的是提供一个 OAuth 2.0 协议的概览以帮助理解,而不是涵盖此协议的所有细节。
如果你计划实现一个 OAuth 2.0 协议,最好是去阅读规范的详细内容,规范的地址:http://tools.ietf.org/html/draft-ietf-oauth-v2-23
在之前的介绍中我们提到,OAuth 2.0 是一个开放标准,其允许应用程序访问其它应用的用户授权的数据。现在我们来介绍这个协议是如何工作的,以及规范中提到的各种概念。
OAuth 2.0 提供了不同的方式去获取权限用语访问资源服务器中的资源。现在介绍其中最安全和最常用的使用方式:一个 web 应用如何请求访问另一个 web 应用的访问权限。
下面的示例图描述了整个处理过程:
首先用户访问客户端应用,在这个应用中会有一个 "通过 Facebook 登录" 的按钮。
第二步,当用户点击这个按钮时,用户被重定向到认证服务器(Facebook)。然后用户开始登录,登录成功后会被询问客户端应用是否可以使用他的用户信息。用户点击确认按钮。
第三步,认证服务器将用户重定向到客户端应用提供的 URL。这个重定向 URL 一般会在认证服务器中进行注册,注册是由客户端应用的所有者进行的。注册完成后,认证服务器会生成一个 client id 和 client password。重定向后的 URL 会有一个 code 参数,该参数是此次认证的一个标识。
第四步,重定向完成后,用户会进入重定向后的页面,同时客户端应用会在后台与认证服务器进行通讯,发送 client id,client password 和上一步获取到的 code 参数到认证服务器,认证服务器返回 access token 给客户端应用。
一旦客户端应用拿到了 access token,就可以用这个 token 去访问 Facebook 提供的相关资源。
OAuth 2.0 定义了以下应用角色:
- Resource Owner(资源所有者)Resource Server(资源服务器)Client Application(客户端应用)Authorization Server(认证服务器)
Resrouce Owner(资源所有者)是数据的所有者。例如:Facebook 或 Google 上的一个用户就是一个 Resrouce Owner。他们所拥有的资源就是用户数据。示例图中的那个用户的图标代表的就是 Resrouce Owner。Resrouce Owner 也可以是一个应用程序。
Resource Server(资源服务器)是存放资源的服务,例如 Facebook 或 Google 就是 Resource Server。
Client Application(客户端应用)会请求访问存放在资源服务器上的资源,这些资源是属于 Resource Owner(资源所有者)的。
Authorization Server(认证服务器)对 Client Application(客户端应用)进行授权,授权通过后客户端应用才可以访问资源服务器上的资源。认证服务器和资源服务器可以是同一个应用,也可以分开独立部署。
OAuth 2.0 规范定义了 2 种客户端类型:
私密型 公开型私密型客户端会保存 client password。认证服务器会给每一个客户端应用生成一个 client password,认证服务器通过该 client password 来识别该客户端应用是一个注册过的应用,而不是其它的欺诈程序。一个 web 应用可以是私密性客户端,只有系统管理员可以登录这个应用的服务器和查看 client password。
公开型客户端不会保存 client password。例如移动 APP 或桌面程序,如果 client password 被保存在此类应用中,就可以通过破解手段拿到 client password,这是非常不安全的。
web 程序运行在 web 服务器上。web 应用做认证时用到的 client password 是保存在服务器上的,因此是私密的。下面是一个 web 应用的示例图:
富 web 客户端应用是指由 javascript 构建的 web 应用,浏览器是客户端代理。这类应用的特点是,程序是存放在 web 服务器上的,但是运行时,浏览器下载 javascript 程序到本地,直接在浏览器中执行,例如那些用 javascript 开发的网页版游戏。下面是一个富 web 客户端的示例图:
(注:这里指没有后端服务器的应用,一次所有的数据和配置只能存放在客户端程序中)
原生应用包括移动 APP 和桌面程序。原生应用直接安装在用户的设备上(电脑或手机、平板),client password 会保存在用户的设备里。下面是一个原生应用的示例图:
这类应用通常是将原生应用和 web 应用的开发技术混合在一起,也会有对应的后端服务器。OAuth 2.0 规范中并没有提及此类应用,此类应用可以灵活选用上述三种认证类型中的任何一种。
当一个客户端应用要访问资源服务器上的资源时,需要先获取到认证授权。
客户端应用需要在认证服务器上注册,注册完成后,认证服务器会生成这个应用的 client id 和 client password。client_id 和 client_password 在同一个认证服务器中是唯一的,不会重复。客户端应用可以在多个认证服务器中进行注册(如分别在 Facebook 和 Google 中注册),不同的认证服务器会为客户端应用生成不同的 client_id 和 client_password。
当客户端应用需要访问资源服务器上的资源时,首选要通过认证服务器进行认证,认证时要发送对应的 client_id 和 client_password 到认证服务器。
客户端应用在认证服务器进行注册时,需要填写一个重定向 URL。当资源所有者对客户端应用进行授权成功后,资源所有者(可简单理解为系统用户)会被重定向到重定向 URL 所指定的页面。
资源所有者会给客户端应用认证授权,认证授权时需要认证服务器和资源服务器进行配合。
OAuth 2.0 规范列举了 4 中认证授权方式,每种方式都有不同的安全特点:
Authorization Code(授权码模式) Implicit(简化模式) Resource Owner Password Credentials(用户密码模式) Client Credentials下面来对每一种授权方式进行解释。
Authorization Code(授权码)的认证过程如下:
资源所有者(用户)进入客户端应用。 客户端应用让用户通过认证服务器进行登录。 登录之前,客户端应用会把用户重定向到认证服务器的登录页面,同时把 client id 发送到认证服务器,这样认证服务器就知道是哪一个客户端应用在请求认证授权。 用户在认证服务器上进行登录,登录成功后,会提示用户是否要对客户端应用进行授权,用户选择同意后,会被重定向回客户端应用。 当重定向回客户端应用时,使用的是客户端应用在认证服务器上注册时填写的重定向 URL,同时认证服务器会发送一个代表此次认证过程的一个授权码。 当成功重定向到客户端应用后,客户端应用会在后台与认证服务器进行交互,将上个步骤中获取到的授权码,连同 client id,client password 发送给认证服务器。 认证服务器对收到的数据进行校验,通过后发送 access token 给客户端应用。 这时客户端应用就可以用接收到的 access token 去资源服务器访问相关资源。下面是一个示例图:Implicit(简化模式)与 Authorization Code(授权码模式)类似,区别仅在于当用户成功登录之后,重定向到客户端应用时,access token 会直接返回给客户端应用。
这意味着 access token 在客户端应用中是可见的。而 Authorization Code(授权码模式),access token 是在 web 服务器中的,对客户端来说不可见。这是这两种模式的最大区别。
并且,客户端应用只发送 client id 到认证服务器。如果连同 client password 一起发送的话,client password 需要存储在客户端应用中,这会是一个安全隐患,很容易通过破解手段拿到存放在客户端应用程序中的 client password。下面是一个示例图:
Resource Owner Password Credentials(密码模式)允许客户端应用直接使用用户的用户名和密码。例如用户可以直接在客户端应用中录入 Twitter 的用户名和密码。
只有在充分信任客户端应用的情况下,才能使用密码模式。(因为用户名和密码是在客户端应用中录入的,因此客户端应用可以获取并保存用户的用户名和密码)。
密码模式一般在富 web 客户端应用和原生应用中使用。
Client Credentials 模式用于访问跟用户无关的资源,因此不需要用户授权。
OAuth 2.0 定义了节点集合。一个节点一般是 web 服务器上的一个 URL。具体包括:
认证节点 Token 节点 重定向节点认证节点和 Token 节点在认证服务器上,重定向节点在客户端应用上。示例图如下:
OAuth 2.0 规范并没有对节点的 URL 做出明确的定义,不同的实现会提供不同的 URL。
认证节点是用户进行登录操作的地址。
Token 节点是认证服务器提供的,让客户端应用获取 access token 的地址。
重定向节点在客户端应用中,用户成功登录后,会被重定向到此地址。
当客户端应用请求 access token 时,会发送 http 请求到认证服务器。不同的认证授权类型会有不同的请求和响应内容。认证授权类型有 4 种:
Authorization Code(授权码模式) Implicit(简化模式) Resource Owner Password Credentials(用户密码模式) Client Credentials每种类型的请求和响应内容会在后续的内容中详细解释。
授权码模式有 2 个请求和 2 个响应:
认证请求+响应 access token 请求+响应。授权请求发送到认证服务器,然后会获取到一个授权码。
- response_type必选项,固定值为"code"client_id必选项,
- 客户端应用在认证服务器注册时生成的client id.redirect_uri可选项.T客户端应用在认证服务器注册时填写的重定向URL地址.scope可选项.请求的权限范围.state可选项 (建议提供).客户端应用的请求URL中的参数,可以是任意值.
授权响应含有授权码,这个授权码在后续获取 access token 时需要提供。
- code必选项.认证服务器返回的授权码.state必选项,
- 如果客户端应用的请求中有这个参数,既为这个参数的值.
授权错误的情形有 2 种。
第一种是客户端应用验证失败,例如授权请求中发送的重定向 URL 与客户端应用在认证服务器中注册时填写的 URL 不一致。
第二种是产生了其它错误,此时下面的错误信息会返回给客户端应用:
- error Required.Must be one of a set of predefined error codes.See the specification
- for the codes and their meaning.error_description Optional.A human - readable UTF - 8 encoded text describing the error.Intended
- for a developer,
- not an end user.error_uri Optional.A URI pointing to a human - readable web page with information about the error.state Required,
- if present in authorization request.The same value as sent in the state parameter in the request.
客户端应用获取到授权码后,可以用此授权码去获取 access token。请求参数如下:
- client_id Required.The client application 's id.
- client_secret Required. The client application's client secret.grant_type Required.Must be set to authorization_code.code Required.The authorization code received by the authorization server.redirect_uri Required,
- if the request URI was included in the authorization request.Must be identical then.
access token 的响应内容是 json 格式的:
- {
- "access_token": "...",
- "token_type": "...",
- "expires_in": "...",
- "refresh_token": "...",
- }
access_token : 访问令牌,
token_type : 令牌类型,一般是 bearer,
expires_in : 以秒为单位的令牌失效时间,
refresh_token : 当访问令牌失效时,可以用更新令牌获取一个新的访问令牌
简化模式只有一个请求和一个响应。
该请求的参数如下:
- response_type Required.Must be set to token.client_id Required.The client identifier as assigned by the authorization server,
- when the client was registered.redirect_uri Optional.The redirect URI registered by the client.scope Optional.The possible scope of the request.state Optional(recommended).Any client state that needs to be passed on to the client request URI.
响应包含以下参数,注意该响应的格式不是 json 的。
- access_token Required.The access token assigned by the authorization server.token_type Required.The type of the token expires_in Recommended.A number of seconds after which the access token expires.scope Optional.The scope of the access token.state Required,
- if present in the autorization request.Must be same value as state parameter in request.
有 2 种情况会导致错误:
第一种是客户端应用验证失败,例如授权请求中发送的重定向 URL 与客户端应用在认证服务器中注册时填写的 URL 不一致。
第二种是产生了其它错误,此时下面的错误信息会返回给客户端应用:
- error Required.Must be one of a set of predefined error codes.See the specification
- for the codes and their meaning.error_description Optional.A human - readable UTF - 8 encoded text describing the error.Intended
- for a developer,
- not an end user.error_uri Optional.A URI pointing to a human - readable web page with information about the error.state Required,
- if present in authorization request.The same value as sent in the state parameter in the request.
用户密码模式只有一个请求和响应。
请求包含以下参数:
- grant_type必选项.固定值"password"username必选项.UTF - 8编码的用户名.password必选项.UTF - 8编码的密码.scope可选项.请求的权限范围.
响应的内容是 json 格式:
- {
- "access_token": "...",
- "token_type": "...",
- "expires_in": "...",
- "refresh_token": "...",
- }
access_token : 访问令牌,
token_type : 令牌类型,
expires_in : 以秒为单位的令牌失效时间,
refresh_token : 当访问令牌失效时,可以用更新令牌获取一个新的访问令牌
请求包含以下参数:
- grant_type必选项.固定值"client_credentials".scope可选项.请求的权限范围.
响应包含以下参数:
- {
- "access_token": "...",
- "token_type": "...",
- "expires_in": "...",
- }
access_token : 访问令牌,
token_type : 令牌类型,
expires_in : 以秒为单位的令牌失效时间,
注意,此种授权类型没有 refresh_token
来源: http://www.2cto.com/kf/201609/544982.html