之前翻譯過(guò)一篇
OAuth認(rèn)證協(xié)議原理分析及使用方法
,雖然 OAuth2還沒(méi)有正式發(fā)布,但是國(guó)內(nèi)外的OAuth2的采用情況幾乎要完全替代掉OAuth1.1了。像淘寶、騰訊、人人網(wǎng)、百度開(kāi)放平臺(tái)就已經(jīng)采用Oauth2,新浪微博也發(fā)來(lái)郵件說(shuō)是要很快上馬OAuth2,徹底替換掉OAuth1.1。目前OAuth2到了
v20草稿階段
,最新的版本是 2011年7月25號(hào)發(fā)布的,協(xié)議變化還是很快的,所以看到國(guó)內(nèi)的一些已經(jīng)實(shí)現(xiàn)的實(shí)例,再比照官方的 oauth2,會(huì)有些出入的。
為何要 OAUTH2來(lái)替換OAUTH1.1?
- 一、OAuth2大大簡(jiǎn)化了認(rèn)證流程,OAuth1版本,我都感覺(jué)有些流程設(shè)計(jì)不是為安全性而存在,有些東西很難想一個(gè)理由,他們?yōu)楹我萌绱藦?fù)雜。復(fù)雜可能是增加安全性的一個(gè)要素,但是也極大增加了開(kāi)發(fā)者的開(kāi)發(fā)難度。
- 二、增加了對(duì)多種不同方式的認(rèn)證,原來(lái)的認(rèn)證只能直接或間接通過(guò)瀏覽器,現(xiàn)在有專(zhuān)門(mén)的標(biāo)準(zhǔn)來(lái)給客戶端程序、移動(dòng)應(yīng)用、瀏覽器應(yīng)用提供認(rèn)證的方法。
OAUTH2的四種角色
- resource owner資源所有者:比如twitter用戶,他在twitter的數(shù)據(jù)就是資源,他自己就是這些資源的所有者。
- resource server資源服務(wù)器:保存資源的服務(wù)器,別人要訪問(wèn)受限制的資源就要出示 Access Token(訪問(wèn)另牌)。
- client客戶端:一個(gè)經(jīng)過(guò)授權(quán)后,可以代表資源所有者訪問(wèn)資源服務(wù)器上受限制資源的一方。比如 開(kāi)發(fā)者開(kāi)發(fā)的應(yīng)用。
- authorization server授權(quán)服務(wù)器:對(duì) 資源所有者進(jìn)行認(rèn)證,認(rèn)證通過(guò)后,向 客戶端發(fā)放 Access Token(訪問(wèn)另牌)。
OAUTH2取得ACCESS TOKEN的四種方式
- 一、Authorization Code授權(quán)碼方式:這種是推薦使用的,也是最安全的,也是替換OAuth1.1的一種授權(quán)方式。
流程:
1、引導(dǎo)用戶訪問(wèn)授權(quán)服務(wù)器,比如地址:
1
2
3
|
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
|
,其中response_type 值固定為 code,client_id就是客戶端申請(qǐng)開(kāi)發(fā)者的時(shí)候取得的 appkey,state是一個(gè)可選參數(shù),可以用于保存客戶端在引導(dǎo)用戶轉(zhuǎn)向前的一些狀態(tài),當(dāng)回到 redirect_uri的時(shí)候會(huì)原封不動(dòng)的傳回來(lái),redirect_uri是當(dāng)用戶確認(rèn)授權(quán)應(yīng)用訪問(wèn)的時(shí)候跳轉(zhuǎn)回來(lái)的地址。
2,用戶同意授權(quán)后跳轉(zhuǎn)回來(lái)的的地址如:
1
2
3
|
HTTP/1.1 302 Found
Location: https:
&state=xyz
|
&state=xyz ,其中 code就是 Authorization Code,state就是上面所說(shuō)的可選參數(shù)。
3,使用取得的 Authorization Code去換取Access Token:
1
2
3
4
5
6
7
|
POST /token HTTP/1.1
Host: server.example.com
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
Content-Type: application/x-www-form-urlencoded;charset=UTF-8
=authorization_code&code=SplxlOBeZQQYbYS6WxSbIA
&redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb
|
其中 Authorization是由Client id(app key)及Client password(app secret)組合成的 http basic 驗(yàn)證字符串,grant_type必須為 authorization_code,code是上一步取得的 Authorization Code,redirect_uri是完成后跳轉(zhuǎn)回來(lái)的網(wǎng)址。
如果Client不能發(fā)送 Authorization信息,則可以使用下面的方式,/token這個(gè)地址必須是 https連接的,不然就有泄露 client secret的可能性:
1
2
3
4
5
6
|
POST /token HTTP/1.1
Host: server.example.com
Content-Type: application/x-www-form-urlencoded;charset=UTF-8
grant_type=refresh_token&refresh_token=tGzv3JOkF0XG5Qx2TlKWIA
&client_id=s6BhdRkqt3&client_secret=7Fjfp0ZBr1KtDRbnfVdmIw
|
成功的話返回的信息為:
1
2
3
4
5
6
7
8
9
10
11
12
|
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"
}
|
- 二、Implicit Grant隱式授權(quán):相比授權(quán)碼授權(quán),隱式授權(quán)少了第一步的取Authorization Code的過(guò)程,而且不會(huì)返回 refresh_token。主要用于無(wú)服務(wù)器端的應(yīng)用,比如 瀏覽器插件。隱式授權(quán)不包含Client授權(quán),它的授權(quán)依賴于 資源所有者及注冊(cè)應(yīng)用時(shí)候所填寫(xiě)的redirection URI(跳轉(zhuǎn)地址)。因?yàn)锳ccess token是附著在 redirect_uri 上面被返回的,所以這個(gè) Access token就可能會(huì)暴露給 資源所有者或者設(shè)置內(nèi)的其它方(對(duì)資源所有者來(lái)說(shuō),可以看到redirect_uri,對(duì)其它方來(lái)說(shuō),可以通過(guò)監(jiān)測(cè)瀏覽器的地址變化來(lái)得到 Access token)。
流程
一、引導(dǎo)用戶訪問(wèn)一個(gè)專(zhuān)門(mén)的授權(quán)頁(yè)面,如
1
2
3
|
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
|
這里的 response_type為 token,client_id為appkey??梢钥吹竭@里取Access token的過(guò)程中并沒(méi)有像 第一種方式那樣傳入 client_secret。因?yàn)槿绻銈魅?client_secret,其實(shí)就是相當(dāng)于告訴用戶,你應(yīng)用的app secret了。
二、在成功授權(quán)后,跳轉(zhuǎn)回到 redirect_uri所定義的網(wǎng)址
1
2
3
|
HTTP/1.1 302 Found
Location: http:
&state=xyz&token_type=example&expires_in=3600
|
,這樣應(yīng)用就可以通過(guò)取地址中的 fragment部分來(lái)取得 access token。
- 三、Resource Owner Password Credentials資源所有者密碼證書(shū)授權(quán):這種驗(yàn)證主要用于資源所有者對(duì)Client有極高的信任度的情況,比如操作系統(tǒng)或高權(quán)限程序。只有在不能使用其它授權(quán)方式的情況下才使用這種方式。
流程:
一、提交信息到取 token頁(yè)面
1
2
3
4
5
6
|
POST /token HTTP/1.1
Host: server.example.com
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
Content-Type: application/x-www-form-urlencoded;charset=UTF-8
grant_type=password&username=johndoe&password=A3ddj3w
|
這里的 Authorization是 client_id為username,client_secret為password的http basic驗(yàn)證碼。grant_type必須為 password,username為用戶名,password為用戶密碼。
取得的結(jié)果如下:
1
2
3
4
5
6
7
8
9
10
11
12
|
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"
}
|
Q:為何要這種這么不安全的方式?
A:取代原來(lái)原始的 username,password的授權(quán)方式,而且不需要 client保存用戶的密碼,client只要保存access token就可以。主要用于客戶端程序。
- 四、Client Credentials客戶端證書(shū)授權(quán):這種情況下 Client使用自己的 client證書(shū)(如 client_id及client_secret組成的 http basic驗(yàn)證碼)來(lái)獲取 access token,只能用于信任的client。
流程:
一、提交參數(shù)取 access token
1
2
3
4
5
6
|
POST /token HTTP/1.1
Host: server.example.com
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
Content-Type: application/x-www-form-urlencoded;charset=UTF-8
grant_type=client_credentials
|
其中 Authorization是client_id及client_secret組成的 http basic驗(yàn)證串。grant_type必須為client_credentials,
返回如下:
1
2
3
4
5
6
7
8
9
10
11
|
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"
}
|
國(guó)內(nèi)一些OAUTH2案例分析
標(biāo)準(zhǔn)的 oauth2中,使用 access token來(lái)向資源服務(wù)器發(fā)出請(qǐng)求,取得資源。這里的資源服務(wù)器需要使用 https協(xié)議,否則access token極可能被其它方獲取。比如
1
2
3
|
GET /resource/1 HTTP/1.1
Host: example.com
Authorization: Bearer 7Fjfp0ZBr1KtDRbnfVdmIw
|
bearer是指 token類(lèi)型
,后面的字符串就是access token。還有一種
mac類(lèi)型的 token(目前v20版本的草稿里還沒(méi)有文檔)
,如:
1
2
3
4
5
|
GET /resource/1 HTTP/1.1
Host: example.com
Authorization: MAC id= "h480djs93hd8" ,
nonce= "274312:dj83hs9s" ,
mac= "kDZvddkndxvhGRXZhvuDjEWhGeE="
|
,因?yàn)?https速度相較http慢,而且并非所有服務(wù)器或客戶都支持https,所以國(guó)內(nèi)一些網(wǎng)站采用一種http也可訪問(wèn)資源的方式。
淘寶開(kāi)放平臺(tái)的方式
:應(yīng)用通過(guò)用戶授權(quán)獲取的AccessToken的值即等同于Sessionkey,應(yīng)用憑借AccessToken調(diào)用taobao API即可。查看淘寶SDK,可以看到 其使用應(yīng)用的app_secret作用密碼鑰來(lái)進(jìn)行簽名,參數(shù)里面包含了 這個(gè)Sessionkey,這樣淘寶在收到這個(gè)請(qǐng)求的時(shí)候,根據(jù) app_id來(lái)判斷是哪個(gè)應(yīng)用,根本sessionkey的值來(lái)判斷是哪個(gè)用戶,如果不傳這個(gè) sessionkey就用 app_id查得app_id所屬的淘寶用戶就行了。也就是說(shuō) sessionkey必須配合 這個(gè) client自己的授權(quán)資料appkey appsrecet來(lái)訪問(wèn)資源。
百度開(kāi)放平臺(tái)方式
、
人人網(wǎng)方式
、還有騰訊也類(lèi)似:在返回 access token的同時(shí)返回 sessionKey及sessionSecret。如:
1
2
3
4
5
6
7
8
|
{
"access_token" : "1.a6b7dbd428f731035f771b8d15063f61.86400.1292922000-2346678-124328" ,
"expires_in" : 86400,
"refresh_token" : "2.385d55f8615fdfd9edb7c4b5ebdc3e39.604800.1293440400-2346678-124328" ,
"scope" : "basic email" ,
"session_key" : "9XNNXe66zOlSassjSKD5gry9BiN61IUEi8IpJmjBwvU07RXP0J3c4GnhZR3GKhMHa1A=" ,
"session_secret" : "27e1be4fdcaa83d7f61c489994ff6ed6" ,
}
|
在調(diào)用資源API的時(shí)候,如下:
1
2
|
GET /rest/2.0/passport/users/getInfo?session_key=9XNNXe66zOlSassjSKD5gry9BiN61IUEi8IpJmjBwvU07RXP0J3c4GnhZR3GKhMHa1A%3D×tamp=2011-06-21+17%3A18%3A09&format=json&uid=67411167&sign=d24dd357a95a2579c410b3a92495f009 HTTP/1.1
Host: api.example.com
|
這里參數(shù)里面的 session_key,傳給服務(wù)器后,用戶查詢 session_secret,sign使用session_secret作為密鑰來(lái)加密的??梢钥吹竭@里調(diào)用的時(shí)候沒(méi)有使用 client_id或client_secret信息,所以對(duì)于任何獲取
1
2
|
"session_key" : "9XNNXe66zOlSassjSKD5gry9BiN61IUEi8IpJmjBwvU07RXP0J3c4GnhZR3GKhMHa1A=" ,
"session_secret" : "27e1be4fdcaa83d7f61c489994ff6ed6" ,
|
的一方都可以調(diào)用到API。降低系統(tǒng)耦合度。
原文地址:http:///oauth2/