OAuth、OAuth2协议-鉴权授权
五种授权模式:
- authorization_code :授权码许可模式(用户即先登录授权中心获取code,再从授权中心获取access_token,以重定向url方式返回access_token给第三方)
模拟过程:
a. 本方已经有注册用户,第三方想用本方注册用户访问本方资源。
b. 第三方作为client在本方已经注册,给它分配了client_id,client_secret,scope,redirect_url,roles等内容。
c. 用户在第三方界面上想访问本方资源时,第三方先把用户界面重定向到本方授权中心去取得授权code,第三方调用或者redirect如下链接:
http://localhost:8080/authz/oauth/authorize?response_type=code&scope=read write&client_id=test&redirect_uri=http%3A%2F%2Flocalhost%3A7777%2Fspring-oauth-client%2Fauthorization_code_callback&state=09876999
链接说明:
response_type: code,返回授权code。
scope: read write, 授权范围为读写。
client_id: test,第三方在本方注册的id。
redirect_uri: 得到授权code后的回调地址,和后续取资源的来源地址需要一致。
state: 第三方状态,整个过程中会保持不变,第三方可以根据这个来实现一些自己特定的安全逻辑。
d. 上面链接界面会判断用户是否已经登录到了本方授权中心(已登录则直接进入授权界面)未登录则先让登录(URL跟上面一样,只是后台根据是否登录来决定是否显示登录界面):
http://localhost:8080/authz/oauth/authorize?response_type=code&scope=read write&client_id=test&redirect_uri=http%3A%2F%2Flocalhost%3A7777%2Fspring-oauth-client%2Fauthorization_code_callback&state=09876999
链接说明:同上。
e. 登录之后进入授权界面(只有同意或不同意两个按钮,实际上client_id、rediect_url等等信息都隐藏在两个表单中):
http://localhost:8080/authz/oauth/authorize
链接说明: 里面隐藏的form,这里只列出同意按钮的:
<form id=’confirmationForm’ name=’confirmationForm’ action=’/authz/oauth/authorize’ method=’post’>
<input type=”hidden” name=”client_id” value=”test”/>
<input type=”hidden” name=”scope” value=”read write”/>
<input type=”hidden” name=”response_type” value=”code”/>
<input type=”hidden” name=”redirect_uri” value=”http://localhost:7777/spring-oauth-client/authorization_code_callback”/>
<input type=”hidden” name=”state” value=”09876999″/>
<input type=”hidden” name=”client_secret” value=””/>
<input name=’user_oauth_approval’ value=’true’ type=’hidden’/>
<label> <input value=’Authorize’ type=’submit’ class=”btn btn-success”/></label>
</form>
f. 如果不同意,则通过重定向url向第三方返回拒绝结果:
http://localhost:7777/spring-oauth-client/authorization_code_callback?error_description=User+denied+access&state=09876999&error=access_denied
链接说明: error:access_denied,访问拒绝。
g. 如果同意,则通过重定向url向第三方返回授权code:
http://localhost:7777/spring-oauth-client/authorization_code_callback?code=440aabaf89f6576744e8719a8a65eb84&state=09876999
链接说明:
http: 为上面带入的重定向url。
code: 440xxxx,为授权code。
h.使用授权code来取得access_token,这个ulr可以随意,但是POST回去的数据需要带client_id、code、等等信息:
http://127.0.0.1:8080/authz/resources/oauth_test.html
链接说明,POST里面的数据:
<form action=”../oauth/token” method=”post” class=”form-horizontal”>
<input type=”text” class=”form-control” id=”client_id” name=”client_id” value=”test” required=”true”/>
<input type=”text” class=”form-control” id=”client_secret” name=”client_secret” value=”test” required=”true”/>
<input type=”text” class=”form-control” id=”grant_type” name=”grant_type” value=”authorization_code” readonly/>
<input type=”text” class=”form-control” id=”redirect_uri” name=”redirect_uri” value=”http://localhost:7777/spring-oauth-client/authorization_code_callback” required=”true”/>
<input type=”text” class=”form-control” id=”code” name=”code” value=”440aabaf89f6576744e8719a8a65eb8″ placeholder=”The code value” required=”true”/>
<button type=”submit” class=”btn btn-primary”>Test ‘code’ get ‘token'</button>
</form>
返回JSON格式access_token:
{“access_token”:”297e1d0cd387a236c1a1411ef109b935″,”refresh_token”:”fc446fe8811fd081013d363bd9da996b”,”token_type”:”Bearer”,”expires_in”:43200}
i. 第三方使用access_token来访问本方资源(当然本方在第三方访问时还是会判断该token是否合法,以及访问的来源url和上面授权时的url是否一致,不合法或不一致还是不能访问资源):
http://localhost:8080/rs/rs/username?access_token=297e1d0cd387a236c1a1411ef109b935
链接说明:后台处理本方资源url时,需要做授权判断,从url的参数里面取得access_token,然后到上面授权中心数据库里面查询该access_token,如果找到,则也可以找到该token对应的用户,当然也就可以返回该用户和该url所对应资源的内容,这个可以使用spring的filter来实现这种访问控制。
- password :密码凭据模式(将用户名、密码传给授权中心,直接获取token)
- client_credentials :客户端凭据模式(无用户,用户向客户端注册,然后客户端以自己的名义向’授权服务中心’获取资源)
- implicit :简化的隐式许可模式(在redirect_uri的Hash传递access_token;Auth客户端运行在浏览器中,如JS、Flash)
- refresh_token :刷新access_token,其实并不是一种独立的授权方式。
摘 要:OAUTH协议为用户资源的授权提供了一个安全的、开放而又简易的标准。与以往的授权方式不同之处是OAUTH的授权不会使第三方触及到用户的帐号信 息(如用户名与密码),即第三方无需使用用户的用户名与密码就可以申请获得该用户资源的授权,因此OAUTH是安全的。同时,任何第三方都可以使用 OAUTH认证服务,任何服务提供商都可以实现自身的OAUTH认证服务,因而OAUTH是开放的。业界提供了OAUTH的多种实现如 PHP,JavaScript,Java,Ruby等各种语言开发包,大大节约了程序员的时间,因而OAUTH是简易的。目前互联网很多服务如Open API,很多大头公司如Google,Yahoo,Microsoft等都提供了OAUTH认证服务,这些都足以说明OAUTH标准逐渐成为开放资源授权 的标准。
一、OAUTH产生的背景
典型案例:如果一个用户拥有两项服务:一项服务是图片在线存储服务A, 另一个是图片在线打印服务B。如下图所示。由于服务A与服务B是由两家不同的服务提供商提供的,所以用户在这两家服务提供商的网站上各自注册了两个用户, 假设这两个用户名各不相同,密码也各不相同。当用户要使用服务B打印存储在服务A上的图片时,用户该如何处理?法一:用户可能先将待打印的图片从服务A上 下载下来并上传到服务B上打印,这种方式安全但处理比较繁琐,效率低下;法二:用户将在服务A上注册的用户名与密码提供给服务B,服务B使用用户的帐号再 去服务A处下载待打印的图片,这种方式效率是提高了,但是安全性大大降低了,服务B可以使用用户的用户名与密码去服务A上查看甚至篡改用户的资源。
很多公司和个人都尝试解决这类问题,包括Google、Yahoo、Microsoft,这也促使OAUTH项目组的产生。OAuth是由Blaine Cook、Chris Messina、Larry Halff 及David Recordon共同发起的,目的在于为API访问授权提供一个开放的标准。OAuth规范的1.0版于2007年12月4日发布。通过官方网址:http://oauth.net可以阅读更多的相关信息。
二、OAUTH简介
在官方网站的首页,可以看到下面这段简介:
An open protocol to allow secure API authorization in a simple and standard method from desktop and web applications.
大概意思是说OAUTH是一种开放的协议,为桌面程序或者基于BS的web应用提供了一种简单的,标准的方式去访问需要用户授权的API服务。OAUTH 类似于Flickr Auth、Google’s AuthSub、Yahoo’s BBAuth、 Facebook Auth等。OAUTH认证授权具有以下特点:
1. 简单:不管是OAUTH服务提供者还是应用开发者,都很容易于理解与使用;
2. 安全:没有涉及到用户密钥等信息,更安全更灵活;
3. 开放:任何服务提供商都可以实现OAUTH,任何软件开发商都可以使用OAUTH;
三、OAUTH相关术语
在弄清楚OAUTH流程之前,我们先了解下OAUTH的一些术语的定义:
- OAUTH相关的三个URL:
- Request Token URL: 获取未授权的Request Token服务地址;
- User Authorization URL: 获取用户授权的Request Token服务地址;
- Access Token URL: 用授权的Request Token换取Access Token的服务地址;
- OAUTH相关的参数定义:
- oauth_consumer_key: 使用者的ID,OAUTH服务的直接使用者是开发者开发出来的应用。所以该参数值的获取一般是要去OAUTH服务提供商处注册一个应用,再获取该应用的oauth_consumer_key。如Yahoo该值的注册地址为:https://developer.yahoo.com/dashboard/
- oauth_consumer_secret:oauth_consumer_key对应的密钥。
- oauth_signature_method: 请求串的签名方法,应用每次向OAUTH三个服务地址发送请求时,必须对请求进行签名。签名的方法有:HMAC-SHA1、RSA-SHA1与PLAINTEXT等三种。
- oauth_signature: 用上面的签名方法对请求的签名。
- oauth_timestamp: 发起请求的时间戳,其值是距1970 00:00:00 GMT的秒数,必须是大于0的整数。本次请求的时间戳必须大于或者等于上次的时间戳。
- oauth_nonce: 随机生成的字符串,用于防止请求的重放,防止外界的非法攻击。
- oauth_version: OAUTH的版本号,可选,其值必须为1.0。
OAUTH HTTP响应代码:
- HTTP 400 Bad Request 请求错误
- Unsupported parameter 参数错误
- Unsupported signature method 签名方法错误
- Missing required parameter 参数丢失
- Duplicated OAuth Protocol Parameter 参数重复
- HTTP 401 Unauthorized 未授权
- Invalid Consumer Key 非法key
- Invalid / expired Token 失效或者非法的token
- Invalid signature 签名非法
- Invalid / used nonce 非法的nonce
四、OAUTH认证授权流程
在弄清楚了OAUTH的术语后,我们可以对OAUTH认证授权的流程进行初步认识。其实,简单的来说,OAUTH认证授权就三个步骤,三句话可以概括:
1. 获取未授权的Request Token
2. 获取用户授权的Request Token
3. 用授权的Request Token换取Access Token
当应用拿到Access Token后,就可以有权访问用户授权的资源了。大家肯能看出来了,这三个步骤不就是对应OAUTH的三个URL服务地址嘛。一点没错,上面的三个步骤 中,每个步骤分别请求一个URL,并且收到相关信息,并且拿到上步的相关信息去请求接下来的URL直到拿到Access Token。具体的步骤如下图所示:
具体每步执行信息如下:
A. 使用者(第三方软件)向OAUTH服务提供商请求未授权的Request Token。向Request Token URL发起请求,请求需要带上的参数见上图。
B. OAUTH服务提供商同意使用者的请求,并向其颁发未经用户授权的oauth_token与对应的oauth_token_secret,并返回给使用者。
C. 使用者向OAUTH服务提供商请求用户授权的Request Token。向User Authorization URL发起请求,请求带上上步拿到的未授权的token与其密钥。
D. OAUTH服务提供商将引导用户授权。该过程可能会提示用户,你想将哪些受保护的资源授权给该应用。此步可能会返回授权的Request Token也可能不返回。如Yahoo OAUTH就不会返回任何信息给使用者。
E. Request Token 授权后,使用者将向Access Token URL发起请求,将上步授权的Request Token换取成Access Token。请求的参数见上图,这个比第一步A多了一个参数就是Request Token。
F. OAUTH服务提供商同意使用者的请求,并向其颁发Access Token与对应的密钥,并返回给使用者。
G. 使用者以后就可以使用上步返回的Access Token访问用户授权的资源。
从上面的步骤可以看出,用户始终没有将其用户名与密码等信息提供给使用者(第三方软件),从而更安全。用OAUTH实现背景一节中的典型案例:当服务 B(打印服务)要访问用户的服务A(图片服务)时,通过OAUTH机制,服务B向服务A请求未经用户授权的Request Token后,服务A将引导用户在服务A的网站上登录,并询问用户是否将图片服务授权给服务B。用户同意后,服务B就可以访问用户在服务A上的图片服务。 整个过程服务B没有触及到用户在服务A的帐号信息。如下图所示,图中的字母对应OAUTH流程中的字母:
OAuth 介绍
OAuth 是一个基于 Token 的 API 认证协议,为用户资源的授权提供了一个更安全更开放的标准。它允许第三方应用在不触及用户的用户名和密码的情况下就可以访问用户受保护的资源。OAuth 应用的一个典型场景如下:如果一个用户在网站 A 存储了自己的图片,想在另一个提供了在线打印服务的网站 B 访问这些图片。A 和 B 是两个不同的服务提供商提供的网站,用户在两个网站上分别注册了用户名和密码。 服务 A 提供了 API 可以获取用户的图片信息,但需要用户的账户信息。打印服务 B 想访问用户存储在 A 上的图片就需要调用这个 API 获取图片并打印。在没有 OAuth 协议出现前,用户只能将自己在 A 上的用户名密码提供给 B,服务 B 再使用用户的账号去调用 A 提供的 API。这样就存在潜在的风险,服务 B 获取了用户在 A 上的用户名密码就可能利用此账号信息篡改用户的资源信息。而是用 OAuth 协议 用户则不必将自己的账号信息告诉 B,A 和 B 之间通过 OAuth 的认证流程达成一个协议,使用 Token 来作为认证的依据,Token 对于用户,A 和 B 来说都是唯一的,从而使得 API 的访问授权更加安全。 如图 4 所示即为 OAuth 的三方交互图:
图 4. OAuth 交互图
图上所示列出了 OAuth 的三个主体:服务提供商,允许其他的应用通过 OAuth 访问他的服务。 用户,在服务提供商网站上拥有独立的账号。第三方消费方,指那些代表用户通过 OAuth 访问服务提供商的服务的网站或应用。 除了这三个主体外,OAuth 还涉及到如下几个术语: consumer key:指第三方应用的唯一标识。第三方应用要想访问某个服务提供商的服务,必须到该服务提供商的网站上注册一个应用,从而获取该应用的 consumer key,作为一个唯一标识。例如 LinkedIn 的注册地址为:https://www.linkedin.com/secure/developer consumer secret: consumer key 对应的密钥,OAuth 的每次请求都要求用密钥进行签名。当应用到服务提供商注册时,就会获取该应用对应的 consumer key 和 consumer secret。 图 5 所示即为整个 OAuth 认证授权的流程图:
图 5. OAuth 认证流程图
整个流程分为三个阶段,首先应用要向服务提供商请求 Request Token,此时的 Request Token 是未经授权的。 而后服务提供商会把用户重定向到自己的网站上请用户进行授权或拒绝。 然后应用得到经过用户授权的 Request Token,使用这个经过授权的 Request Token 向服务提供商交换 Access Token。 得到 Access Token 后应用就可以用这个 Token 作为标识来访问服务提供商提供的服务了,直到这个 token 过期,否则应用可以一直直接使用其来获取服务,而无需再去进行认证授权。 从以上三个阶段可以看出,服务提供商必须提供以下三个 URL:
- Request Token URL: 获取未授权的 Request Token 服务地址;
- User Authorization URL: 获取用户授权的 Request Token 服务地址;
- Access Token URL: 用授权的 Request Token 换取 Access Token 的服务地址。
每个支持 OAuth 的服务提供商都会提供这三个 URL,第三方应用在开发支持 OAuth 的消费方时就需要配置 consumer key,consumer secret 和这三个 URL。 具体每一步的消息如下:
- A. 第三方应用向 OAuth 服务提供商请求未授权的 Request Token。向 Request Token URL 发起请求,请求需要带上 consumer key 和 consumer secret。
- B. OAuth 服务提供商同意使用者的请求,并向其颁发未经用户授权的 Request Token 与对应的 Token Secret,并返回给使用者。
- C. 使用者向 OAuth 服务提供商请求用户授权的 Request Token。向 User Authorization URL 发起请求,请求带上上步拿到的未授权的 token 与其密钥。第三方应用可以自动完成此步,直接将用户重定向到服务提供商的登录页面。
- D. OAUTH 服务提供商请求用户授权。该过程可能会提示用户,是否将受保护的资源授权给该应用,并且可以设置这个授权的期限。
- E. Request Token 被授权后,应用将向 Access Token URL 发起请求,将上步授权的 Request Token 换取成 Access Token。
- F. OAUTH 服务提供商同意使用者的请求,并向其颁发 Access Token 与对应的密钥,并返回给使用者。
- G. 使用者以后就可以使用上步返回的 Access Token 访问用户授权的资源。
OAuth 协议是安全的,在整个认证的过程中,用户在服务提供商的账户信息都没有暴露给第三方应用。OAuth 也是开放的,任何第三方应用 都可以使用 OAuth 认证服务,任何服务提供商都可以实现自己的 OAuth 认证服务,只要符合整个 OAuth 的协议。业界目前有 OAuth 的多种实现,Java,Ruby 等 很多开源工具包,大大节约了开发者的时间。目前很多网站都是 OAuth 的服务提供商,如 Google,Yahoo, MySpace, LinkedIn, Facebook,Twitter 等。 OAuth 的协议标准目前广泛采用的为 1.0a,OAuth 2.0 现在还是 IETF 的 draft 版本,很多网站已经开始支持 OAuth2.0。
OpenSocial 中的 OAuth 应用场景
在介绍了 OAuth 的认证流程后,我们来看在 OpenSocial 的环境中使用 OAuth 的场景。 OpenSocial 的开发者并不需要关心 OAuth 认证的具体流程,因为客户端的开发包已经完成了大部分的流程,开发人员只要完成对应的配置就好。 OAuth 协议里规定所有的请求必须被签名,这样接收方就能够根据这个签名判断这个请求是来自特定的应用并且确认传输的过程是没有被破坏的。 OpenSocial 也是使用这个对请求签名的方法,允许第三方开发者验证传向他们的社会化数据是来自特定的容器的。典型的应用为: 从 Gadget 传输社会化数据到应用服务器;从应用服务器请求数据在 Gadget 中显示。请求的流程如下: 1. 运行在某个社交网站的 Gadget 希望传输数据到远程服务器,Gadget 可以通过数据流或是 osapi.http 的方法来指定一个特定的签名请求。 2. 这个请求首先会先传输到 Gadget 容器,容器会将合适的社会化数据绑定到请求,并用 OAuth 的签名方法对请求进行签名。 3. 远方的应用服务器接收到这个请求,首先确认请求没有再传输的过程破坏,而后将所请求的应用数据返回并在 Gadget 中显示。
OpenSocial 和两方的 OAuth
两方指的是社交网络和应用服务器,社会化的应用(Social Application)需要运行在一个社交网站才更有意义。使用两方的 OAuth, 社交网站才可以安全的和应用服务器通过 OAuth 的签名请求来交换数据。在两方的 OAuth 中,并不涉及认证授权的步骤,默认应用服务器 已经获得了社交网络的授权,可以从其获取数据。这通常是用户安装这个应用到社交网络时就会授权应用可以访问用户在该网站的数据。 比如,用户发现一个很好玩的社会化应用,想要安装到自己的 MySpace 中,在安装的过程中该应用就会请求用户授权访问 MySpace 的数据。
OpenSocial 和三方的 OAuth
三方指的是社交网络,应用服务器和应用用户。三方和两方的一个显著区别就是需要用户的参与,需要用户的授权, 因为这个应用此时是运行在社交网络之外的第三方服务器上,需要访问社交网络的数据,就需要通过 OAuth 的协议流程完成授权。 两方 OAuth 的可以简单的理解为应用安装在社交网络里,访问所在社交网络的数据。三方的则是应用没有安装在这个社交网站上需要访问他的数据。 比如:安装在 igoogle 的 Gadget 访问 igoogle 的用户数据就是两方的,如果这个 Gadget 需要访问用户在 MySpace 的用户数据,就是三方的,需要用户在 MySpace 的授权。
Shindig 对 OAuth 的支持
Shindig 不仅可以作为 OAuth 的服务提供商,也可以作为第三方应用的消费方,访问其他网站的服务。 ShindigGadget 容器会代理所有的 Gadget 完成 OAuth 所需的认证流程,开发人员所做的就是完成 OAuth 所需的配置就好。 Shindig 提供了 oauthpopup 的特性负责在 Gadget 需要用户授权时弹出窗口。 Shindig 作为 OAuth 的服务提供商,开发的 Gadget 可以使用 OAuth 协议来访问 Shindig 提供的服务。比如开发一个 Gadget 使用 OAuth 来访问 Shindig 提供的 REST API,实际的例子可参考 Shindig 提供的 shindigoauth.xml。 同时,Shindig 也作为第三方应用,可以使用 OAuth 来访问其他服务提供商的 API。下面以开发一个 Gadget 在 Shindig 中运行来访问 LinkedIn 的服务为例来说明:
首先开发人员需要到 LinkedIn 的网站注册一下自己的应用,获取 consumer key 和 consumer secret。 第二步,在 Shindig 中配置 LinkedIn 的服务,找到 oauth.json 文件,将 consumer key 和 consumer secret 配置到 Shindig。 配置时需要以 Gadget 的 URL 作为键值,比如我们开发的 Gadget 叫 test_linkedin.xml,我们将这个服务命名为 linkedin。具体的配置如下所示:
清单 4 . 在 oauthjson 中填加 LinkedIn 的服务
“http://localhost:8080/container/test_linkedin.xml” : {
“linkedin” : {
“consumer_key”:”bUXNL2pxlKzwXBCGbQgVMMQPUVUA1kVKzKJryGHxnCK_FLFcX5vc7ES6Tzg9dK1x”,
“consumer_secret”:”euYkALWxdC9_CbYBpePARuRb-ytS5fgI0m3gwm7tFmD6taO8YeU3mEIN5Kv0z3MD”,
“key_type” : “HMAC_SYMMETRIC”
}
}
|
第三步就可以开发 Gadget 了,在 Gadget 中需要在 ModulePrefs 中声明 OAuth 的服务,并且将 LinkedIn 的三个 URL 声明,如下所示:
|
清单 5 . Gadget 中的 OAuth 声明
<ModulePrefs title=”Test_Linkedin_service”>
<OAuth>
<Service name=”linkedin”>
<Access url=”https://api.linkedin.com/uas/oauth/accessToken” method=”POST” />
<Request url=”https://api.linkedin.com/uas/oauth/requestToken” method=”POST” />
<Authorization url=”https://api.linkedin.com/uas/oauth/authorize?oauth_callback=http://localhost:8080/vulcan/shindig/gadgets/oauthcallback” />
</Service>
</OAuth>
<Require feature=”oauthpopup” />
</ModulePrefs>
|
对于需要 OAuth 认证的 Gadget,一般提供了三个 UI 的部分,一个是认证前,提示用户连接到服务提供商定制 Gadget;一个是用户点击了定制后在进行认证过程中的 UI 显示;一个就是完成认证之后的实际数据显示。 oauthpopup 特性在用户点击定制时会打开一个新的窗口,当用户认证完成时会自动检测到关闭窗口。初始 UI 如图 6 所示:
图 6. 初始请求用户定制 Gadget
当用户点击定制的链接时,即打开 LinkedIn 的登录界面,如图 7 所示:
图 7. 引导用户到 LinkedIn 登录授权
清单 6 . Gadget 中发送请求的代码
var params = {};
var url = “https://api.linkedin.com/v1/people/~”;
params[gadgets.io.RequestParameters.CONTENT_TYPE] = gadgets.io.ContentType.DOM;
params[gadgets.io.RequestParameters.AUTHORIZATION] = gadgets.io.AuthorizationType.OAUTH;
params[gadgets.io.RequestParameters.OAUTH_SERVICE_NAME] = “linkedin”;
params[gadgets.io.RequestParameters.METHOD] = gadgets.io.MethodType.GET;
gadgets.io.makeRequest(url, function (response) {
if (response.oauthApprovalUrl) {
var onOpen = function() {
showOneSection(‘waiting’);
};
var onClose = function() {
onLoad();
};
var popup = new gadgets.oauth.Popup(response.oauthApprovalUrl,
null, onOpen, onClose);
$(‘personalize’).onclick = popup.createOpenerOnClick();
$(‘approvaldone’).onclick = popup.createApprovedOnClick();
showOneSection(‘approval’);
} else if (response.data) {
showOneSection(‘main’);
showResults(response.data);
} else {
// The response.oauthError and response.oauthErrorText values may help debug
// problems with your gadget.
var main = document.getElementById(‘main’);
var err = document.createTextNode(‘OAuth error: ‘ +
response.oauthError + ‘: ‘ + response.oauthErrorText);
main.appendChild(err);
showOneSection(‘main’);
}
}, params);
|
以上所示为 Gadget 中发送请求到 LinkedIn 的逻辑,当没有经过 OAuth 认证时,makerequest 返回的 response 中会有一项 oauthApprovalUrl, 打开对应的 URL 重定向用户到 LinkedIn 的登录页面请用户授权。此时 Gadget 的 UI 显示正在授权中的状态,如图 8 所示。当用户授权完成后 ,UI 就直接显示 API 返回的数据了。 本示例返回作者在 LinkedIn 的基本信息,如图 9 所示:
图 8. 当用户授权时 Gadget 的 UI 显示
图 9. 授权完成后的数据显示
当用户认证过后就可以直接从 LinkedIn 取到所需的数据,直到该授权过期都不需要再让用户授权了。详细的示例读者可以参考本文提供的示例下载。 Shindig 的 Gadget 容器会负责保存用户的 Access Token,目前是存储在内存里,所以当服务器重启 Access Token 就丢失了。 需要使用 Shindig 作为实际的容器时可以将 Token 保存到数据库,实现更完善的服务。