`
djb4ke
  • 浏览: 55112 次
  • 性别: Icon_minigender_1
  • 来自: 苏州
社区版块
存档分类
最新评论

OAuth in OpenSocial-第一篇:3-legged OAuth实例分析(Shindig)

阅读更多

3-legged OAuth

在Shindig上RUN OAuth Demo

#设置Shindig的KeyStore

为了跑完整的OAuth流程,我们需要在Server端保存OAuth consumer的key和secret

打开文件 %SHINDIG_ROOT%/target/work/webapp/WEB-INF/classes/config/oauth.json

这个文件就是OAuth的配置文件,因为我们要run的是Shindig默认的OAuth例子,所以这里已经定义好了,如果以后要自己要添加在,仿照着加进去即可。

shindigoauth config in OAuth.json
"http://localhost:8080/samplecontainer/examples/shindigoauth.xml" : {
"shindig" : {
"consumer_key" : "http://localhost:8080/samplecontainer/examples/shindigoauth.xml",
"consumer_secret" : "secret",
"key_type" : "HMAC_SYMMETRIC"
}
}

 

同时,我们还需要生成server端自己的key:

Step1 :到链接处下载Openssl, http://www.slproweb.com/products/Win32OpenSSL.html

Step2 :用下面两个命令可以生成key

openssl req -newkey rsa:1024 -days 365 -nodes -x509 -keyout testkey.pem  -out testkey.pem -subj '/CN=mytestkey'

openssl pkcs8 -in testkey.pem -out oauthkey.pem -topk8 -nocrypt -outform PEM

 

示例-在我的环境下生成key的情形
C:\OpenSSL\bin>openssl req -newkey rsa:1024 -days 365 -nodes -x509 -keyout testk
ey.pem -out testkey.pem -subj '/CN=mytestkey'
Loading 'screen' into random state - done
Generating a 1024 bit RSA private key
.....++++++
........................++++++
writing new private key to 'testkey.pem'
-----
Subject does not start with '/'.
problems making Certificate Request

C:\OpenSSL\bin>openssl pkcs8 -in testkey.pem -out oauthkey.pem -topk8 -nocrypt -
outform PEM

 

Step3 :编辑SHINDIG_ROOT/java/common/conf/shindig.properties文件

为shindig.signing.key-name和shindig.signing.key-file属性赋值

shindig.signing.key-file是你存放oauthkey.pem 的位置。

shindig.properties
.......
### Outbound OAuth support
shindig.signing.state-key=
shindig.signing.key-name=mykey
shindig.signing.key-file=C://OpenSSL//bin//oauthkey.pem
shindig.signing.global-callback-url=http://localhost:8080/gadgets/oauthcallback
shindig.signing.enable-signed-callbacks=true
........

 

保存后需要重新编译shindig:

step1 : mvn clean

step2 : mvn(或者可以忽略test,用mvn -Dmaven.test.skip=true)

 

编译完成后启动Shindig

mvn -Prun

 

 

打开浏览器:

进入Shindig默认测试container: http://localhost:8080/samplecontainer/samplecontainer.html

在Displaying gadget输入: http://localhost:8080/samplecontainer/examples/shindigoauth.xml

点击reset all后会render出gadget。

点击Button后会进行Oauth的flow.

 

误区: 跑完一遍如果没有截HTTP报文分析,从表面来看,可能误解这是Gadget与Server在交互,Gadget用自己的secret和key来对Server发OAuth请求,Server端hold了这对key/secret,似乎make sense。

但是如果稍微深入想想,Gadget被Render出来后只是段HTML,不通过server,怎么能发出OAuth这么复杂的request呢,而request当然也不可能是被Gadget正在访问的服务发的(自己验证自己多没意义╮(╯_╰)╭)。那这到底是怎么做的呢

而且此时的环境是我单独运行的Shindig,用的gadget也是shindig自带的,似乎一切都在shindig中完成,并没有OAuth中consumer和service provider的概念,如果不把Gadget当做cousumer,就更加费解了..

 

为了说明这个问题,首先引入OpenSocial OAuth的Flow

 

Image:Oauth_3legged.png
  1. A user wishes to use their social network data inside of a third party website or application. The application server contacts the social network, but does not have the user's account information, and does not have permission to access the user's data.

  2. The social network responds with information that the application server uses to redirect the user's web browser to a special login page on the social network's domain.

  3. If the user is logged out of the social network, they input their username and password as if they were normally logging into the site. After they log in, or if they were already logged in (with a cookie), they are asked by the social network to share data with the application.

  4. Once permission has been granted, the social network redirects the user's web browser to a predefined URL on the application server, along with a token that can be used to access the user's information.

  5. Using the token as described in the OAuth specification, the application server is now able to access the user's data on the social network.

Image:Oauth_legend.png

 

 

对Http Analyzer截获的整个OAuth过程结合上面的流程图进行分析

 



※标号是按时间排序的Shindig Demo OAuth各步骤:

 

①gadget makeRequest

这一步就跟OpenSocial的第一个描述一致(不是第一步),用户在Gadget中需要访问些他们在第三方的数据,这是典型的OAuth应用场景,但是让裸露的Gadget发送OAuth Request显然不合适:第一,Gadget在何处存放key/secret?明文么?显然不能。第二,Gadget不适合做复杂算法,比如签名等?更何况签名如果用RAS算法,还需用到证书,证书放哪里??所以如Open Social OAuth的第0步,Gadget对App Server发起一个OAuth的请求,即makeRequest

 

细节看下面

Gadget make request
POST /gadgets/makeRequest HTTP/1.1
Host: 127.0.0.1:8080
Connection: keep-alive
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/533.1 (KHTML, like Gecko) Chrome/5.0.335.1 Safari/533.1
Referer: http://127.0.0.1:8080/gadgets/ifr?container=default&mid=0&nocache=0&country=ALL&lang=ALL&view=default&parent=http%3A%2F%2Flocalhost%3A8080&st=john.doe%3Ajohn.doe%3A6114%3Ashindig%3Ahttp%253A//localhost%253A8080/samplecontainer/examples/shindigoauth.xml%3A0%3Adefault&url=http%3A%2F%2Flocalhost%3A8080%2Fsamplecontainer%2Fexamples%2Fshindigoauth.xml
Content-Length: 521
Origin: http://127.0.0.1:8080
Content-Type: application/x-www-form-urlencoded
Accept: */*
Accept-Encoding: gzip,deflate,sdch
Accept-Language: zh-CN,zh;q=0.8
Accept-Charset: GBK,utf-8;q=0.7,*;q=0.3
Cookie: __utmz=96992031.1272262237.1.1.utmcsr=localhost:8080|utmccn=(referral)|utmcmd=referral|utmcct=/samplecontainer/samplecontainer.html; __utma=96992031.311100061.1272262237.1272262237.1272262237.1; __utmv=96992031.container%2Fshindig

POST Data:
url http://localhost:8080/social/rest/people/@me/@self
st john.doe:john.doe:6114:shindig:http%3A//localhost%3A8080/samplecontainer/examples/shindigoauth.xml:0:default
signViewer true
signOwner true
postData
OAUTH_SERVICE_NAME shindig
oauthState
numEntries 3
httpMethod GET
headers
getSummaries false
getFullHeaders false
gadget http://localhost:8080/samplecontainer/examples/shindigoauth.xml
contentType TEXT
container default
bypassSpecCache 0
authz oauth

由上可见,Gadget post给App Server的data,是一些基本信息,比如要请求的资源,Viewer/Owner,app id,server名字和是否签名等,并不是具体的OAuth Request

 

 

②:App Server向Social Network发送具体的OAuth请求

此步骤对应spec flow中的第一步,实际发起请求的是App server。

 

细节如下:

Real OAuth Request
GET /oauth/requestToken HTTP/1.1

Authorization: OAuth oauth_callback="http://localhost:8080/gadgets/oauthcallback?cs=DrcUT0ehRxQ0NOrOWaX1W8R5FTVx1nhYmIPjbsVN8rqayhBlVACrTEzM%2F31RZAhsgHGjulkPfcEeC5ohKK%2BFRJseFhIWoNm5RLO%2FS524PnbPzgEswAITYX0dGHAAL8D5hNAVfpyjCuwN%2BK2F3MwddjBjRbI%3D",
opensocial_owner_id="john.doe",
opensocial_viewer_id="john.doe",
opensocial_app_id="6114", opensocial_app_url="http://localhost:8080/samplecontainer/examples/shindigoauth.xml",
oauth_version="1.0",
oauth_timestamp="1272366999",
oauth_consumer_key="http://localhost:8080/samplecontainer/examples/shindigoauth.xml",
oauth_signature_method="HMAC-SHA1",
oauth_nonce="97398594831985",
oauth_signature="/TMZ0kErj5W0v1YzuieRxzN3rdE="

X-shindig-dos: on
Host: localhost:8080
Connection: Keep-Alive
User-Agent: Apache Shindig

 

通过对比,可以清楚地看出,此处OAuth Request是在Gadget发出的request基础上产生的,比如opensocial_owner_id,opensocial_viewer_id,opensocial_app_id,opensocial_app_url等,都是一致的。

 

请求发过去后,Social network会返回响应(针对App Server),将Request Token带回来。

Social Network 返回的相应
HTTP/1.1 200 OK
Content-Type: text/plain
Expires: Tue, 27 Apr 2010 11:16:39 GMT
Pragma: no-cache
Cache-Control: no-cache
Content-Length: 134
Server: Jetty(6.1.22)

oauth_token=b57e1ba2-9eb7-49aa-8a44-89ccf4d6cace&oauth_token_secret=f615ed6a-2fc3-45d9-92bf-9b57a7f1f935&oauth_callback_confirmed=true

 

App Server得到Request Token后,返回给Gadget(这里的返回是Http Log中的①的返回)

细节

 

App Server对Gadget返回的响应
HTTP/1.1 200 OK
Content-Type: application/json; charset=UTF-8
Expires: Tue, 27 Apr 2010 11:16:39 GMT
Pragma: no-cache
Cache-Control: no-cache
Content-Disposition: attachment;filename=p.txt
Content-Length: 525
Server: Jetty(6.1.22)

throw 1; < don't be evil' > {"http://localhost:8080/social/rest/people/@me/@self": {"oauthState":"y83Tu8QcQPQr9M0O9ioY97vuOgRRE/XmXJe9fCd5eAj2gSG0s6uo0Me51GpPVtylOjsz3L/8rBJWu0EBAEMPkSTVNwhXCqqnuZFGgKYjMXSKGJfYlMi7Z++dWCT/Jrc4Z3W3hZF4ZKXhaD3SaxxZh3KE9epJeSil2hqLxLu39X+Z29/+rSO3aC9qJ84g8Q/eqcqu2Q==","body":"","DataHash":"qgeopmcf02p09qc016cepu22fo","oauthApprovalUrl":"http://localhost:8080/oauth/authorize?oauth_callback=http://localhost:8080/gadgets/oauthcallback&oauth_token=b57e1ba2-9eb7-49aa-8a44-89ccf4d6cace","rc":200}}

 

 

 

③得到Request Token后,点击Gadget中的按钮,重定向用户去Login page做login(同Open Social Spec Flow 第二步)

 

Gadget中的Button点击后,到了Social Network的OAuth Endpoint,发现用户未认证,于是302重定向到loginpage

真相如下=_=#

Gadget对Social Network发起的认证Request
GET /oauth/authorize?oauth_callback=http://localhost:8080/gadgets/oauthcallback&oauth_token=b57e1ba2-9eb7-49aa-8a44-89ccf4d6cace HTTP/1.1
Host: localhost:8080
Connection: keep-alive
.......

 

Social Network发现未通过认证,将User重定向到LoginPage
HTTP/1.1 302 Found
Expires: Thu, 01 Jan 1970 00:00:00 GMT
Set-Cookie: JSESSIONID=xby7iy65qukg;Path=/
Location: http://localhost:8080/login.jsp;jsessionid=xby7iy65qukg
Content-Length: 0
Server: Jetty(6.1.22)

 

到了LoginPage后,通过form完成Login,登录完成后,Social Network又将user agent 302重定向,回到/oauth/authorize?oauth_callback=http://localhost:8080/gadgets/oauthcallback&oauth_token=b57e1ba2-9eb7-49aa-8a44-89ccf4d6cace 再次确认是否已经通过认证。

 

Post Login form
POST /login.jsp;jsessionid=xby7iy65qukg HTTP/1.1
........

username=canonical&password=password&submit=Login

 

Login OK, Response with 302...重定向回/oauth/authorize 写道
HTTP/1.1 302 Found
Location: http://localhost:8080/oauth/authorize?oauth_callback=http://localhost:8080/gadgets/oauthcallback&oauth_token=b57e1ba2-9eb7-49aa-8a44-89ccf4d6cace
Content-Length: 0
Server: Jetty(6.1.22)

 

④授权..(同Open Social Spec Flow 第三步)

继续接着上面...302后,User Agent被定向到  http://localhost:8080/oauth/authorize

此时由于我们已经完成登录,即身份认证完成,因此social Network返回我们授权页面

Gadget再次确认自己是否认证通过
GET /oauth/authorize?oauth_callback=http://localhost:8080/gadgets/oauthcallback&oauth_token=b57e1ba2-9eb7-49aa-8a44-89ccf4d6cace HTTP/1.1
......

 

social network确认身份后, 200 OK,并返回授权的form 写道
HTTP/1.1 200 OK
.......

<form name="authZForm" action="authorize" method="POST">
<input type="hidden" name="oauth_token" value="b57e1ba2-9eb7-49aa-8a44-89ccf4d6cace"/>
<input type="hidden" name="oauth_callback" value="http%3A%2F%2Flocalhost%3A8080%2Fgadgets%2Foauthcallback%3Fcs%3DDrcUT0ehRxQ0NOrOWaX1W8R5FTVx1nhYmIPjbsVN8rqayhBlVACrTEzM%252F31RZAhsgHGjulkPfcEeC5ohKK%252BFRJseFhIWoNm5RLO%252FS524PnbPzgEswAITYX0dGHAAL8D5hNAVfpyjCuwN%252BK2F3MwddjBjRbI%253D"/>
<input type="submit" name="Authorize" value="Deny"/>
<input type="submit" name="Authorize" value="Authorize"/>
</form>

 

点击 Authorize后授权通过,根据协议,完成授权后,因为有oauth_callback参数,所以此时social network应该将user agent 302重定向至oauth_callback,事实也确实如此。

 

user-agent post 授权信息至Social Network
POST /oauth/authorize HTTP/1.1
Host: localhost:8080
Connection: keep-alive
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/533.1 (KHTML, like Gecko) Chrome/5.0.335.1 Safari/533.1
Referer: http://localhost:8080/oauth/authorize?oauth_callback=http://localhost:8080/gadgets/oauthcallback&oauth_token=b57e1ba2-9eb7-49aa-8a44-89ccf4d6cace
Content-Length: 349
Cache-Control: max-age=0
Origin: http://localhost:8080
Content-Type: application/x-www-form-urlencoded
Accept: application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
Accept-Encoding: gzip,deflate,sdch
Accept-Language: zh-CN,zh;q=0.8
Accept-Charset: GBK,utf-8;q=0.7,*;q=0.3
Cookie: JSESSIONID=xby7iy65qukg

oauth_token =b57e1ba2-9eb7-49aa-8a44-89ccf4d6cace
&oauth_callback =http%253A%252F%252Flocalhost%253A8080%252Fgadgets%252Foauthcallback%253Fcs%253DDrcUT0ehRxQ0NOrOWaX1W8R5FTVx1nhYmIPjbsVN8rqayhBlVACrTEzM%25252F31RZAhsgHGjulkPfcEeC5ohKK%25252BFRJseFhIWoNm5RLO%25252FS524PnbPzgEswAITYX0dGHAAL8D5hNAVfpyjCuwN%25252BK2F3MwddjBjRbI%25253D
&Authorize =Authorize
Social Network确认授权请求,通过请求后,将user-agent重定向至oauth_callback..(同Open Social Spec Flow 第四步)
HTTP/1.1 302 Found
Expires: Tue, 27 Apr 2010 11:17:44 GMT
Pragma: no-cache
Cache-Control: no-cache
Content-Type: text/html; charset=utf-8
Location: http://localhost:8080/gadgets/oauthcallback?cs=DrcUT0ehRxQ0NOrOWaX1W8R5FTVx1nhYmIPjbsVN8rqayhBlVACrTEzM%2F31RZAhsgHGjulkPfcEeC5ohKK%2BFRJseFhIWoNm5RLO%2FS524PnbPzgEswAITYX0dGHAAL8D5hNAVfpyjCuwN%2BK2F3MwddjBjRbI%3D&oauth_token=b57e1ba2-9eb7-49aa-8a44-89ccf4d6cace&user_id=canonical&oauth_verifier=806728
Content-Length: 0
Server: Jetty(6.1.22)

 

User-Agent访问oauth_callback后,App Server 返回响应,302 重定向User-agent至..如下

Location: http://127.0.0.1:8080/gadgets/oauthcallback?oauth_token=b57e1ba2-9eb7-49aa-8a44-89ccf4d6cace&user_id=canonical&oauth_verifier=806728

#_#这里略掉LOG了,否则显得太婆妈了

访问重定向的地址后,响应中是一段关闭窗口的脚本,将OAuth窗口关闭。

 

⑤得到已授权的request token后,user-agent再次make request

此次的request是Gadget通过app server向social site获取access token

User Agent向APP server发起请求
POST /gadgets/makeRequest HTTP/1.1
Host: 127.0.0.1:8080
Connection: keep-alive
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/533.1 (KHTML, like Gecko) Chrome/5.0.335.1 Safari/533.1
Referer: http://127.0.0.1:8080/gadgets/ifr?container=default&mid=0&nocache=0&country=ALL&lang=ALL&view=default&parent=http%3A%2F%2Flocalhost%3A8080&st=john.doe%3Ajohn.doe%3A6114%3Ashindig%3Ahttp%253A//localhost%253A8080/samplecontainer/examples/shindigoauth.xml%3A0%3Adefault&url=http%3A%2F%2Flocalhost%3A8080%2Fsamplecontainer%2Fexamples%2Fshindigoauth.xml
Content-Length: 924
Origin: http://127.0.0.1:8080
Content-Type: application/x-www-form-urlencoded
Accept: */*
Accept-Encoding: gzip,deflate,sdch
Accept-Language: zh-CN,zh;q=0.8
Accept-Charset: GBK,utf-8;q=0.7,*;q=0.3
Cookie: __utmz=96992031.1272262237.1.1.utmcsr=localhost:8080|utmccn=(referral)|utmcmd=referral|utmcct=/samplecontainer/samplecontainer.html; __utma=96992031.311100061.1272262237.1272262237.1272262237.1; __utmv=96992031.container%2Fshindig

url http://localhost:8080/social/rest/people/@me/@self
httpMethod GET
headers
postData
authz oauth
st john.doe:john.doe:6114:shindig:http%3A//localhost%3A8080/samplecontainer/examples/shindigoauth.xml:0:default
contentType TEXT
numEntries 3
getSummaries false
signOwner true
signViewer true
gadget http://localhost:8080/samplecontainer/examples/shindigoauth.xml
container default
bypassSpecCache 0
getFullHeaders false
OAUTH_RECEIVED_CALLBACK http://127.0.0.1:8080/gadgets/oauthcallback?oauth_token=b57e1ba2-9eb7-49aa-8a44-89ccf4d6cace&user_id=canonical&oauth_verifier=806728
oauthState y83Tu8QcQPQr9M0O9ioY97vuOgRRE/XmXJe9fCd5eAj2gSG0s6uo0Me51GpPVtylOjsz3L/8rBJWu0EBAEMPkSTVNwhXCqqnuZFGgKYjMXSKGJfYlMi7Z++dWCT/Jrc4Z3W3hZF4ZKXhaD3SaxxZh3KE9epJeSil2hqLxLu39X+Z29/+rSO3aC9qJ84g8Q/eqcqu2Q==
OAUTH_SERVICE_NAME shindig

 

⑥App Server得到gadget发来的请求后,随即向Social site发起获取OAuth access token的请求

App Server根据Gadget提供的request信息组装OAuth request发至Social Site
GET /oauth/accessToken HTTP/1.1
Authorization: OAuth oauth_token="b57e1ba2-9eb7-49aa-8a44-89ccf4d6cace",
oauth_verifier="806728",
opensocial_owner_id="john.doe",
opensocial_viewer_id="john.doe",
opensocial_app_id="6114",
opensocial_app_url="http%3A%2F%2Flocalhost%3A8080%2Fsamplecontainer%2Fexamples%2Fshindigoauth.xml",
oauth_version="1.0",
oauth_timestamp="1272367066",
oauth_consumer_key="http%3A%2F%2Flocalhost%3A8080%2Fsamplecontainer%2Fexamples%2Fshindigoauth.xml",
oauth_signature_method="HMAC-SHA1",
oauth_nonce="97464950537801",
oauth_signature="bBefDNJ08JL3Q%2BGw7LwFAoBS6Q0%3D"
X-shindig-dos: on
Host: localhost:8080
Connection: Keep-Alive
User-Agent: Apache Shindig
Accept-Encoding: gzip, deflate



 

返回Access Token至social site
HTTP/1.1 200 OK
Expires: Tue, 27 Apr 2010 11:17:46 GMT
Pragma: no-cache
Cache-Control: no-cache
Content-Type: text/plain
Content-Length: 122
Server: Jetty(6.1.22)

oauth_token=2bc02874-b62b-4b5d-b241-a42ddc7141f3&oauth_token_secret=715d0f5b-7f43-4d48-8adf-c56f40c9b5c8&user_id=canonical

⑦app server使用access token获取个人的数据

App server向Social site通过access token发起获取数据的请求
GET /social/rest/people/@me/@self HTTP/1.1
Authorization: OAuth oauth_body_hash="2jmj7l5rSw0yVb%2FvlWAYkK%2FYBwk%3D", opensocial_owner_id="john.doe", opensocial_viewer_id="john.doe", opensocial_app_id="6114", opensocial_app_url="http%3A%2F%2Flocalhost%3A8080%2Fsamplecontainer%2Fexamples%2Fshindigoauth.xml", oauth_version="1.0", oauth_timestamp="1272367066", oauth_token="2bc02874-b62b-4b5d-b241-a42ddc7141f3", oauth_consumer_key="http%3A%2F%2Flocalhost%3A8080%2Fsamplecontainer%2Fexamples%2Fshindigoauth.xml", oauth_signature_method="HMAC-SHA1", oauth_nonce="97465826497985", oauth_signature="9nHr7S%2BgKV5Cm1WRvfSGxoeXbrE%3D"
X-Forwarded-For: 127.0.0.1
X-shindig-dos: on
Host: localhost:8080
Connection: Keep-Alive
User-Agent: Apache Shindig
Accept-Encoding: gzip, deflate

 

social site确认请求后返回私人数据
HTTP/1.1 200 OK
Content-Type: application/json; charset=UTF-8
Content-Length: 331
Server: Jetty(6.1.22)

{"entry":{"id":"canonical","thumbnailUrl":"http://www.example.org/pic/?id=1","name":{"formatted":"Sir Shin H. Digg Social Butterfly","honorificPrefix":"Sir","additionalName":"H","familyName":"Digg","givenName":"Shin","honorificSuffix":"Social Butterfly"},"photos":[{"value":"http://www.example.org/pic/?id=1","type":"thumbnail"}]}}

 

得到数据后,app server将私人数据返回至gadget,此处的返回是第⑤步Gadget请求的返回
HTTP/1.1 200 OK
Expires: Tue, 27 Apr 2010 12:17:47 GMT
Cache-Control: public,max-age=3600
Content-Type: application/json; charset=UTF-8
Content-Disposition: attachment;filename=p.txt
Content-Length: 735
Server: Jetty(6.1.22)

throw 1; < don't be evil' >{"http://localhost:8080/social/rest/people/@me/@self":{"oauthState":"Sa/ZmzpOYDY3YW5UQjjxdg7tbCrJQ1MZFe8QloX5jlNuS6hhijt9AGEacojSJhaSpjjbOdImcmC/vY9H2YxIuThKLDwnWmLDLePfRhJb0G/76G5ujwPjlL/yG97HwY0+XhPo05EfZEDgLRMjXAb40VdUORFx6jm6PnbRxB9x8NLxFI7RD4QHibOfAsXvEf0Au4WvlA==","body":"{\"entry\":{\"id\":\"canonical\",\"thumbnailUrl\":\"http://www.example.org/pic/?id=1\",\"name\":{\"formatted\":\"Sir Shin H. Digg Social Butterfly\",\"honorificPrefix\":\"Sir\",\"additionalName\":\"H\",\"familyName\":\"Digg\",\"givenName\":\"Shin\",\"honorificSuffix\":\"Social Butterfly\"},\"photos\":[{\"value\":\"http://www.example.org/pic/?id=1\",\"type\":\"thumbnail\"}]}}","DataHash":"f5qmubv18f1jpp37caai4ok1sc","rc":200}}

 

⑥⑦同spec flow中的第五步

 

reference:

http://oauth.net/core/1.0a

http://wiki.opensocial.org/index.php?title=OAuth_Use_Cases  

 

 


 
 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 大小: 38.7 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics