大数据

OAuth 2.0 简介

OAuth 简介:

OAuth.png

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

OAuth 2.0 是 OAuth协议的下一版本,但不向后兼容 OAuth 1.0。 OAuth 2.0关注客户端开发者的简易性,同时为Web应用,桌面应用和手机,和起居室设备提供专门的认证流程,目前主要使用的版本是2.0版。

一、应用场景

为了理解OAuth的适用场合,让我举一个假设的例子。
有一个”云冲印”的网站,可以将用户储存在Google的照片,冲印出来。用户为了使用该服务,必须让”云冲印”读取自己储存在Google上的照片。

网易云冲印.png

问题是只有得到用户的授权,Google才会同意”云冲印”读取这些照片。那么,”云冲印”怎样获得用户的授权呢?
传统方法是,用户将自己的Google用户名和密码,告诉”云冲印”,后者就可以读取用户的照片了。这样的做法有以下几个严重的缺点:

  1. “云冲印”为了后续的服务,会保存用户的密码,这样很不安全。

  2. Google不得不部署密码登录,而我们知道,单纯的密码登录并不安全。

  3. “云冲印”拥有了获取用户储存在Google所有资料的权力,用户没法限制”云冲印”获得授权的范围和有效期。

  4. 用户只有修改密码,才能收回赋予”云冲印”的权力。但是这样做,会使得其他所有获得用户授权的第三方应用程序全部失效。

  5. 只要有一个第三方应用程序被破解,就会导致用户密码泄漏,以及所有被密码保护的数据泄漏。

OAuth就是为了解决上面这些问题而诞生的。

对于用户相关的OpenAPI(例如获取用户信息,动态同步,照片,日志,分享等),为了保护用户数据的安全和隐私,第三方移动应用访问用户数据前都需要显式的向用户征求授权。

二、协议的参与者

OAuth的参与实体至少有如下三个:

  • RO (resource owner): 资源所有者,对资源具有授权能力的人。如用户Alice。

  • RS (resource server): 资源服务器,它存储资源,并处理对资源的访问请求。如Google资源服务器,它所保管的资源就是用户Alice的照片。

  • Client: 第三方应用,它获得RO的授权后便可以去访问RO的资源。如网易印像服务。

此外,为了支持开放授权功能以及更好地描述开放授权协议,OAuth引入了第四个参与实体:

  • AS (authorization server): 授权服务器,它认证RO的身份,为RO提供授权审批流程,并最终颁发授权令牌(Access Token)。

读者请注意,为了便于协议的描述,这里只是在逻辑上把AS与RS区分开来;在物理上,AS与RS的功能可以由同一个服务器来提供服务。

在详细讲解OAuth 2.0之前,需要了解几个专用名词。它们对读懂后面的讲解,尤其是几张图,至关重要:

  1. Third-party application:第三方应用程序,本文中又称”客户端”(client),即上一节例子中的”云冲印”。

  2. HTTP service:HTTP服务提供商,本文中简称”服务提供商”,即上一节例子中的Google。

  3. Resource Owner:资源所有者,本文中又称”用户”(user)。

  4. User Agent:用户代理,本文中就是指浏览器。

  5. Authorization server:认证服务器,即服务提供商专门用来处理认证的服务器。

  6. Resource server:资源服务器,即服务提供商存放用户生成的资源的服务器。它与认证服务器,可以是同一台服务器,也可以是不同的服务器。

知道了上面这些名词,就不难理解,OAuth的作用就是让”客户端”安全可控地获取”用户”的授权,与”服务商提供商”进行互动。

三、OAuth 的思路

OAuth在”客户端”与”服务提供商”之间,设置了一个授权层(authorization layer)。”客户端”不能直接登录”服务提供商”,只能登录授权层,以此将用户与客户端区分开来。”客户端”登录授权层所用的令牌(token),与用户的密码不同。用户可以在登录的时候,指定授权层令牌的权限范围和有效期。

“客户端”登录授权层以后,”服务提供商”根据令牌的权限范围和有效期,向”客户端”开放用户储存的资料。

四、运行流程

OAuth协议 – 基本流程:

OAuth协议 – 基本流程.jpg

如图1所示,协议的基本流程如下:

  1. Client请求RO的授权,请求中一般包含:要访问的资源路径,操作类型,Client的身份等信息。

  2. RO批准授权,并将“授权证据”发送给Client。至于RO如何批准,这个是协议之外的事情。典型的做法是,AS提供授权审批界面,让RO显式批准。这个可以参考下一节实例化分析中的描述。

  3. Client向AS请求“访问令牌(Access Token)”。此时,Client需向AS提供RO的“授权证据”,以及Client自己身份的凭证。

  4. AS验证通过后,向Client返回“访问令牌”。访问令牌也有多种类型,若为bearer类型,那么谁持有访问令牌,谁就能访问资源。

  5. Client携带“访问令牌”访问RS上的资源。在令牌的有效期内,Client可以多次携带令牌去访问资源。

  6. RS验证令牌的有效性,比如是否伪造、是否越权、是否过期,验证通过后,才能提供服务。

不难看出来,上面六个步骤之中,(2)是关键,即用户怎样才能给于客户端授权。有了这个授权以后,客户端就可以获取令牌,进而凭令牌获取资源。

下面一一讲解客户端获取授权的四种模式。

五、客户端的授权模式

客户端必须得到用户的授权(authorization grant),才能获得令牌(access token)。OAuth 2.0定义了四种授权方式。

  • 授权码模式(authorization code)

  • 简化模式(implicit)

  • 密码模式(resource owner password credentials)

  • 客户端模式(client credentials)

5.1 授权码模式

授权码模式(authorization code)是功能最完整、流程最严密的授权模式。它的特点就是通过客户端的后台服务器,与”服务提供商”的认证服务器进行互动。

授权码模式.png

它的步骤如下:
(A)用户访问客户端,后者将前者导向认证服务器。
(B)用户选择是否给予客户端授权。
(C)假设用户给予授权,认证服务器将用户导向客户端事先指定的”重定向URI”(redirection URI),同时附上一个授权码。
(D)客户端收到授权码,附上早先的”重定向URI”,向认证服务器申请令牌。这一步是在客户端的后台的服务器上完成的,对用户不可见。
(E)认证服务器核对了授权码和重定向URI,确认无误后,向客户端发送访问令牌(access token)和更新令牌(refresh token)。

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

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

  • response_type:表示授权类型,必选项,此处的值固定为”code”

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

  • redirect_uri:表示重定向URI,可选项

  • scope:表示申请的权限范围,可选项

  • state:表示客户端的当前状态,可以指定任意值,认证服务器会原封不动地返回这个值。

例如:

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

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

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

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

例如:

HTTP/1.1 302 FoundLocation:[https://client.example.com/cb](https://client.example.com/cb)?code=SplxlOBeZQQYbYS6WxSbIA &state=xyz

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

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

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

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

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

例如:

POST /token HTTP/1.1Host: server.example.comAuthorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JWContent-Type: application/x-www-form-urlencodedgrant_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":"example","expires_in":3600,"refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA","example_parameter":"example_value"}

从上面代码可以看到,相关参数使用JSON格式发送(Content-Type: application/json)。此外,HTTP头信息中明确指定不得缓存。

举例:下面我以实例化方式来帮助读者理解授权码类型的授权协议的运行过程。假设:

(1) Alice有一个有效的Google帐号;

(2) Facebook.com已经在Google Authorization Server上注册了Client身份,已经获得(client_id, client_secret),注意client_secret是Client与AS之间的一个共享密钥。

(3) Alice想授权Facebook.com查看她的联系人列表(https://www.google.com/m8/feeds) 。

下图展示了Alice、Facebook.com、Google资源服务器、以及Google OAuth授权服务器之间的协议运行过程。

运行过程.jpg

协议所涉及到的细节都已经在图3上了,所以不打算再做详细介绍了。若看懂了此图,OAuth2.0就理解了。

读者请注意,在步骤(4)中,Client需要拿“授权码”去换“授权令牌”时,Client需要向AS证明自己的身份,即证明自己就是步骤(2)中Alice批准授权时的Grantee。这个身份证明的方法主要有两种(图3中使用了第1种):

(1) 通过https直接将client_secret发送给AS,因为client_secret是由Client与AS所共享,所以只要传送client_secret的信道安全即可。

(2) 通过消息认证码来认证Client身份,典型的算法有HMAC-SHA1。在这种方式下,Client无需传送client_secret,只需发送消息请求的signature即可。由于不需要向AS传递敏感数据,所以它只需要使用http即可。

此外,在步骤(2)中,Google授权服务器需要认证Alice的RO身份,并提供授权界面给Alice进行授权审批。今天Google提供的实例如图4、图5所示,仅供读者理解OAuth这种“现场授权”或”在线授权”的含义。

登录.jpg

权限.jpg

为何引入authorization_code?

协议设计中,为什么要使用authorization_code来交换access_token?这是读者容易想到的一个问题。也就是说,在协议的第3步,为什么不直接将access_token通过重定向方式返回给Client呢?比如:

HTTP/1.1 302Location:https://www.facebook.com/?access_token=ya29.AHES6ZSXVKYTW2VAGZtnMjD&token_type=Bearer&expires_in=3600

如果直接返回access_token,协议将变得更加简洁,而且少一次Client与AS之间的交互,性能也更优。那为何不这么设计呢?协议文档[1]中并没有给出这样设计的理由,但也不难分析:

(1) 浏览器的redirect_uri是一个不安全信道,此方式不适合于传递敏感数据(如access_token)。因为uri可能通过HTTP referrer被传递给其它恶意站点,也可能存在于浏览器cacher或log文件中,这就给攻击者盗取access_token带来了很多机会。另 外,此协议也不应该假设RO用户代理的行为是可信赖的,因为RO的浏览器可能早已被攻击者植入了跨站脚本用来监听access_token。因 此,access_token通过RO的用户代理传递给Client,会显著扩大access_token被泄露的风险。 但authorization_code可以通过redirect_uri方式来传递,是因为authorization_code并不像 access_token一样敏感。即使authorization_code被泄露,攻击者也无法直接拿到access_token,因为拿 authorization_code去交换access_token是需要验证Client的真实身份。也就是说,除了Client之外,其他人拿 authorization_code是没有用的。 此外,access_token应该只颁发给Client使用,其他任何主体(包括RO)都不应该获取access_token。协议的设计应能保证 Client是唯一有能力获取access_token的主体。引入authorization_code之后,便可以保证Client是 access_token的唯一持有人。当然,Client也是唯一的有义务需要保护access_token不被泄露。

(2) 引入authorization_code还会带来如下的好处。由于协议需要验证Client的身份,如果不引入authorization_code, 这个Client的身份认证只能通过第1步的redirect_uri来传递。同样由于redirect_uri是一个不安全信道,这就额外要求 Client必须使用数字签名技术来进行身份认证,而不能用简单的密码或口令认证方式。引入authorization_code之后,AS可以直接对 Client进行身份认证(见步骤4和5),而且可以支持任意的Client认证方式(比如,简单地直接将Client端密钥发送给AS)。

5.2 简化模式

简化模式(implicit grant type)不通过第三方应用程序的服务器,直接在浏览器中向认证服务器申请令牌,跳过了”授权码”这个步骤,因此得名。所有步骤在浏览器中完成,令牌对访问者是可见的,且客户端不需要认证。

简化模式.png

它的步骤如下:

(A)客户端将用户导向认证服务器。

(B)用户决定是否给于客户端授权。

(C)假设用户给予授权,认证服务器将用户导向客户端指定的”重定向URI”,并在URI的Hash部分包含了访问令牌。

(D)浏览器向资源服务器发出请求,其中不包括上一步收到的Hash值。

(E)资源服务器返回一个网页,其中包含的代码可以获取Hash值中的令牌。

(F)浏览器执行上一步获得的脚本,提取出令牌。

(G)浏览器将令牌发给客户端。

下面是上面这些步骤所需要的参数:
A 步骤中,客户端发出的HTTP请求,包含以下参数:

  • response_type:表示授权类型,此处的值固定为”token”,必选项。

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

  • redirect_uri:表示重定向的URI,可选项。

  • scope:表示权限范围,可选项。

  • state:表示客户端的当前状态,可以指定任意值,认证服务器会原封不动地返回这个值。

例如:

GET /authorize?response_type=token&client_id=s6BhdRkqt3&state=xyz &redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb HTTP/1.1 Host: server.example.com

C 步骤中,认证服务器回应客户端的URI,包含以下参数:

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

  • token_type:表示令牌类型,该值大小写不敏感,必选项。

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

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

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

例如:

HTTP/1.1 302 Found Location: [http://example.com/cb](http://example.com/cb)#access_token=2YotnFZFEjr1zCsicMWpAA &state=xyz&token_type=example&expires_in=3600

在上面的例子中,认证服务器用HTTP头信息的Location栏,指定浏览器重定向的网址。注意,在这个网址的Hash部分包含了令牌。

根据上面的D步骤,下一步浏览器会访问Location指定的网址,但是Hash部分不会发送。接下来的E步骤,服务提供商的资源服务器发送过来的代码,会提取出Hash中的令牌。

5.3 密码模式

密码模式(Resource Owner Password Credentials Grant)中,用户向客户端提供自己的用户名和密码。客户端使用这些信息,向”服务商提供商”索要授权。

在这种模式中,用户必须把自己的密码给客户端,但是客户端不得储存密码。这通常用在用户对客户端高度信任的情况下,比如客户端是操作系统的一部分,或者由一个著名公司出品。而认证服务器只有在其他授权模式无法执行的情况下,才能考虑使用这种模式。

密码模式.png

它的步骤如下:

(A)用户向客户端提供用户名和密码。

(B)客户端将用户名和密码发给认证服务器,向后者请求令牌。

(C)认证服务器确认无误后,向客户端提供访问令牌。

B 步骤中,客户端发出的HTTP请求,包含以下参数:

  • grant_type:表示授权类型,此处的值固定为”password”,必选项。

  • username:表示用户名,必选项。

  • password:表示用户的密码,必选项。

  • scope:表示权限范围,可选项。

例如:

POST /token HTTP/1.1 Host: server.example.com Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW Content-Type: application/x-www-form-urlencoded grant_type=password&username=johndoe&password=A3ddj3w

C 步骤中,认证服务器向客户端发送访问令牌,下面是一个例子。

HTTP/1.1 200 OK Content-Type: application/json;charset=UTF-8 Cache-Control: no-store Pragma: no-cache{"access_token":"2YotnFZFEjr1zCsicMWpAA","token_type":"example","expires_in":3600,"refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA","example_parameter":"example_value"}

上面代码中,各个参数的含义参见《授权码模式》一节。

整个过程中,客户端不得保存用户的密码。

5.4 客户端模式

客户端模式(Client Credentials Grant)指客户端以自己的名义,而不是以用户的名义,向”服务提供商”进行认证。严格地说,客户端模式并不属于OAuth框架所要解决的问题。在这种模式中,用户直接向客户端注册,客户端以自己的名义要求”服务提供商”提供服务,其实不存在授权问题。

客户端模式.png

它的步骤如下:

(A)客户端向认证服务器进行身份认证,并要求一个访问令牌。

(B)认证服务器确认无误后,向客户端提供访问令牌。

A 步骤中,客户端发出的HTTP请求,包含以下参数:

  • granttype:表示授权类型,此处的值固定为”clientcredentials”,必选项。

  • scope:表示权限范围,可选项。

    POST /token HTTP/1.1 Host: server.example.com Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW Content-Type: application/x-www-form-urlencoded grant_type=client_credentials

认证服务器必须以某种方式,验证客户端身份。

B 步骤中,认证服务器向客户端发送访问令牌,下面是一个例子。

HTTP/1.1 200 OK Content-Type: application/json;charset=UTF-8 Cache-Control: no-store Pragma: no-cache{"access_token":"2YotnFZFEjr1zCsicMWpAA","token_type":"example","expires_in":3600,"example_parameter":"example_value"}

上面代码中,各个参数的含义参见《授权码模式》一节。

六、更新令牌

如果用户访问的时候,客户端的”访问令牌”已经过期,则需要使用”更新令牌”申请一个新的访问令牌。
客户端发出更新令牌的HTTP请求,包含以下参数:

  • granttype:表示使用的授权模式,此处的值固定为”refreshtoken”,必选项。
  • refresh_token:表示早前收到的更新令牌,必选项。
  • scope:表示申请的授权范围,不可以超出上一次申请的范围,如果省略该参数,则表示与上一次一致。

下面是一个例子。

 POST /token HTTP/1.1
 Host: server.example.com
 Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
 Content-Type: application/x-www-form-urlencoded

 grant_type=refresh_token&refresh_token=tGzv3JOkF0XG5Qx2TlKWIA

七、案例 —— 通过QQ的开放平台,实现第三方服务通过用户的QQ登录:

1、QQ登录OAuth2.0接入方式:

移动应用可通过以下两种方式接入:

(1)使用QQ互联提供的SDK包,用户体验统一,只需要修改少量代码,不需要理解验证授权流程,需要快速接入QQ登录的移动应用可选用此方法。详见:SDK下载

(2)根据QQ登录OAuth2.0协议,自主开发,此方法自定义程度较高,需要与现有系统进行整合的移动应用可选用此方法。详见:OAuth2.0开发文档

2、QQ登录OAuth2.0总体处理流程:

Step1:接入申请,获取appid和apikey


接入QQ登录前,需要首先进行申请,获得对应的appid与appkey,以保证后续流程中可正确对 应用 与 用户 进行验证与授权。

同时,需要保证连接畅通。

申请appid和appkey的用途:

appid:应用的唯一标识。在OAuth2.0认证过程中,appid的值即为oauth_consumer_key的值。

appkey:appid对应的密钥,访问用户资源时用来验证应用的合法性。在OAuth2.0认证过程中,appkey的值即为 oauth_consumer_secret的值。

申请地址:
http://connect.qq.com/intro/login/

申请流程:

  1. 点击页面上的“申请加入”按钮,申请成为开发者;

  2. 申请appid(oauth_consumer_key/client_id)和appkey(auth_consumer_secret/client_secret):

(1)进入 http://connect.qq.com/manage/ 页面,点击“添加移动应用”,在弹出的对话框中填写应用移动的名称;

(2)点击“确定”按钮,提交资料后,获取appid和appkey。

注意:申请appid时,登录的QQ号码将与申请到的appid绑定,后续维护均需要使用该号码。

Tips:
注意对appid和appkey信息进行保密,不要随意泄漏。

Step2:放置QQ登录按钮


在移动应用界面上放置“QQ登录”按钮,并为按钮添加前台代码,实现点击按钮即弹出QQ登录对话框。

  1. 将按钮放置在页面合适的位置
    移动应用需要使用腾讯方提供的“QQ登录”按钮图片,放置在页面合适的位置。

  2. 为“QQ登录”按钮添加前台代码
    2.1 效果演示
    用户在页面上点击“QQ登录”按钮,将触发QQ登录对话框,效果如下图所示:

QQ登录.png

2.2 前台代码
为了实现上述效果,应该为“QQ登录”按钮图片添加如下前台代码:

Step3:通过用户登录验证和授权,获取Access Token


通过用户验证登录和授权,获取Access Token,为下一步获取用户的OpenID做准备;同时,Access Token是应用在调用OpenAPI访问和修改用户数据时必须传入的参数。access token由每次用户登录时生成,过期时间默认为三个月,用户再次登录时自动刷新,请移动应用做好防过期策略,或过期后提示用户再次授权。

QQ登录OAuth2.0针对移动应用接入,提供了登录验证和授权流程,主要提供以下获取access token的方式:
client-side模式
即OAuth官方文档中提到的Implicit模式,适用于需要通过客户端访问的方式。

  1. client-side模式 简介

client-side模式,是OAuth2.0认证的一种模式,又称User-Agent Flow;适用于需要通过客户端访问的方式,例如需要通过浏览器的javascript代码,或者电脑/移动终端上的客户端访问时。

其授权验证流程示意图如下(图片来源:OAuth2.0协议草案V21的4.2节

授权验证流程.png

对于应用而言,只需要一步:构造授权地址,即可获取Access_Token。

2. 过程详解

请求地址:
https://graph.qq.com/oauth2.0/authorize

请求方法:
GET

请求参数:

参数.png

返回说明

  1. 如果用户成功登录并授权,则会跳转到指定的回调地址,并在URL后加“#”号,带上Access Token以及expires_in等参数。如果请求参数中传入了state,这里会带上原始的state值。如果redirect_uri地址后已经有“#”号,则加“&”号,带上相应的返回参数。如:
http://graph.qq.com/demo/index.jsp?#access_token=FE04************************CCE2&expires_in=7776000&state=test

说明:expires_in是该access token的有效期,单位为秒。

Tips:

  1. 可通过js方法:window.location.hash来获取URL中#后的参数值。2. 建议用js设置cookie存储token。

  2. 如果用户在登录授权过程中取消登录流程,登录页面直接关闭。

错误码说明

接口调用有错误时,会返回code和msg字段,以url参数对的形式返回,value部分会进行url编码(UTF-8)。

错误码详细信息请参见:移动应用接入时的公共返回码

Step4:通过Access Token获取用户的OpenID


通过输入在上一步获取的Access Token,得到对应用户身份的OpenID。

OpenID是此网站上或应用中唯一对应用户身份的标识,网站或应用可将此ID进行存储,便于用户下次登录时辨识其身份,或将其与用户在网站上或应用中的原有账号进行绑定。

1.请求地址

移动应用:https://graph.qq.com/oauth2.0/meWAP网站:https://graph.z.qq.com/moc2/me

2.请求方法

GET

3 请求参数

请求参数请包含如下内容:

参数.png

4 返回说明

PC网站接入时,获取到用户OpenID,返回包如下:

callback( {"client_id":"YOUR_APPID","openid":"YOUR_OPENID"} );

WAP网站接入时,返回如下字符串:

client_id=100222222&openid=1704************************878C

openid是此网站上唯一对应用户身份的标识,网站可将此ID进行存储便于用户下次登录时辨识其身份,或将其与用户在网站上的原有账号进行绑定。

5 错误码说明

接口调用有错误时,会返回code和msg字段,以url参数对的形式返回,value部分会进行url编码(UTF-8)。

WAP网站接入时,错误码详细信息请参见:9000-9999:根据Access Token获得对应用户身份的openid时,发生错误

Step5:调用OpenAPI,来请求访问或修改用户授权的资源。


获取到Access Token后OpenID后,可通过调用OpenAPI来获取或修改用户个人信息。

调用OpenAPI时需要用到如下3个值:

  • YOUR_APP_ID:即申请QQ登录成功后分配的appid(如222222)

  • YOUR_ACCESS_TOKEN:Step3获取到的Access Token,必须保证未过期(如E0632E6CE12AC709999)

  • YOUR_OPENID:Step4获取到的OpenID,用户唯一标识(如B9DD537D1C5C98A9999)

  1. 前提说明
    1.1 该appid已经开通了该OpenAPI的使用权限。
    API列表的接口列表中可以看到,有的接口是完全开放的,有的接口则需要提前提交申请,以获取访问权限。
    2.2 准备访问的资源是用户授权可访问的。
    网站调用该OpenAPI读写某个openid(用户)的信息时,必须是该用户已经对你的appid进行了该OpenAPI的授权(例如用户已经设置了相册不对外公开,则网站是无法读取照片信息的)。
    用户可以进入QQ空间->设置->授权管理进行访问权限的设置。
    3.3 已经成功获取到Access Token,并且Access Token在有效期内。

  2. 调用OpenAPI接口
    QQ登录提供了用户信息/动态同步/日志/相册/微博等OpenAPI(详见API列表),网站需要将请求发送到某个具体的OpenAPI接口,以访问或修改用户数据。

调用所有OpenAPI时,除了各接口私有的参数外,所有OpenAPI都需要传入基于OAuth2.0协议的通用参数:

参数.png

3.示例

1.以get_simple_userinfo接口为例:(请将access_token,appid等参数值替换为你自己的)

https://graph.qq.com/user/get_simple_userinfo?access_token=1234ABD1234ABD&oauth_consumer_key=12345& openid=B08D412EEC4000FFC37CAABBDC1234CC&format=json

2.成功返回后,即可获取到用户数据:

{
"ret":0,
"msg":"",
"nickname":"Peter",
"figureurl":"http://qzapp.qlogo.cn/qzapp/111111/942FEA70050EEAFBD4DCE2C1FC775E56/30",
"figureurl_1":"http://qzapp.qlogo.cn/qzapp/111111/942FEA70050EEAFBD4DCE2C1FC775E56/50",
"figureurl_2":"http://qzapp.qlogo.cn/qzapp/111111/942FEA70050EEAFBD4DCE2C1FC775E56/100",
"figureurl_qq_1":"http://q.qlogo.cn/qqapp/100312990/DE1931D5330620DBD07FB4A5422917B6/41",
"figureurl_qq_2":"http://q.qlogo.cn/qqapp/100312990/DE1931D5330620DBD07FB4A5422917B6/100",
"is_yellow_vip":"1", 
"is_yellow_year_vip":"0",
"yellow_vip_level":"6"
}