本文分兩部分送爸,第一部分介紹OAuth基礎(chǔ)知識(shí)暖释,第二部分展示一個(gè)Demo,使用百度OAuth SDK獲取令牌信息與用戶信息球匕。
詳細(xì)代碼:github.com/Baolvlv/LearnAndroid/tree/master/OAuthDemo
一亮曹、OAuth基礎(chǔ)知識(shí)
1.OAuth概述與運(yùn)行流程
OAuth是關(guān)于授權(quán)(authorization)的開放的網(wǎng)絡(luò)標(biāo)準(zhǔn)照卦,用戶允許第三方應(yīng)用訪問用戶在某一網(wǎng)站上的私密資源役耕,而不需將用戶名與密碼提供給第三方應(yīng)用,通過OAuth訪問可以限制第三方應(yīng)用的范圍和有效期故慈。
2006年11月察绷,OpenID不能滿足twitter的委托授權(quán)
2007年4月拆撼,成立OAuth討論小組
2007年11月闸度,OAuth核心1.0最后的草案發(fā)布
2010年4月,OAuth1.0協(xié)議發(fā)布 ?RFC-5849
2012年12月娶视,OAuth2.0協(xié)議發(fā)布 RFC-6749
OAuth 2.0不向下兼容OAuth 1.0
+--------+?????????????????????????????? +---------------+
|??????? |--(A)- Authorization Request ->|?? Resource??? |
|??????? |?????????????????????????????? |???? Owner???? |
|??????? |<-(B)-- Authorization Grant ---|?????????????? |
|??????? |?????????????????????????????? +---------------+
|??????? |
|??????? |?????????????????????????????? +---------------+
|??????? |--(C)-- Authorization Grant -->| Authorization |
| Client |?????????????????????????????? |???? Server??? |
|第三方應(yīng)用 |<-(D)----- Access Token ———|??授權(quán)服務(wù)器?????? |
|??????? |????????????(令牌)??????????? +---------------+
|??????? |
|??????? |?????????????????????????????? +---------------+
|??????? |--(E)----- Access Token ------>|??? Resource?? |
|??????? |?????????????????????????????? |???? Server??? |
|??????? |<-(F)--- Protected Resource ---|?????????????? |
+--------+?????????????????????????????? +———————+
2.OAuth授權(quán)模式
1.授權(quán)碼模式(Authorization Code)
2.簡(jiǎn)化模式(implicit grant)
3.密碼模式(resource owner password credentials)
4.客戶端模式(client credentials)
授權(quán)碼模式最完整嚴(yán)密,下圖為授權(quán)碼模式流程
+----------+
| Resource |
|?? Owner? |
|????????? |
+----------+
^
|
(B)
+----|-----+????????? Client Identifier????? +---------------+
|???????? -+----(A)-- & Redirection URI ---->|?????????????? |
|? User-?? |???????????????????????????????? | Authorization |
|? Agent? -+----(B)-- User authenticates --->|???? Server??? |
|????????? |???????????????????????????????? |?????????????? |
用戶代理?? -+----(C)-- Authorization Code ---<|?????????????? |
+-|----|---+???????????????????????????????? +---------------+
|??? |???????????????????????????????????????? ^????? v
(A)? (C)??????????????????????????????????????? |????? |
|??? |???????????????????????????????????????? |????? |
^??? v???????????????????????????????????????? |????? |
+---------+????????????????????????????????????? |????? |
|???????? |>---(D)-- Authorization Code ---------'????? |
|? Client |????????? & Redirection URI????????????????? |
|???????? |???????????????????????????????????????????? |
|???????? |<---(E)----- Access Token -------------------'
+---------+?????? (w/ Optional Refresh Token)
Note: The lines illustrating steps (A), (B), and (C) are broken into
two parts as they pass through the user-agent.
Figure 3: Authorization Code Flow
Redirection URI———重定向URIOptional Refresh Token———刷新令牌
客戶端發(fā)起兩次請(qǐng)求,第一次以獲得臨時(shí)授權(quán)碼作為結(jié)束青柄,第二次以獲得令牌作為結(jié)束
用戶代理一般為瀏覽器
第一次請(qǐng)求參數(shù):
第一次請(qǐng)求返回參數(shù):
第二次請(qǐng)求參數(shù):
請(qǐng)求方式:
第二次請(qǐng)求需要客戶端的ID與密鑰
現(xiàn)在普遍使用Https,當(dāng)使用Https時(shí)双戳,get和post請(qǐng)求安全性相同飒货,get方式更加便捷峭竣。
使用http+Basic時(shí)皆撩,使用post方式更為安全毅访,請(qǐng)求信息不可以在url中直接讀取喻粹,post會(huì)將請(qǐng)求內(nèi)容隱藏到請(qǐng)求實(shí)體中草巡。
Content-Type:申請(qǐng)的表單類型
grant_type:請(qǐng)求實(shí)體
Http Basic Authentication:
訪問一個(gè)特定的域名或url時(shí),需要通過用戶名和密碼進(jìn)行授權(quán)查看
發(fā)起請(qǐng)求時(shí)攜帶用戶名和密碼信息:
post方式和get方式:
代碼實(shí)現(xiàn):post方式:
第二次請(qǐng)求返回參數(shù):
access_token:令牌,expires_in:令牌的有效時(shí)間段
refresh_token:刷新令牌由境,令牌實(shí)效后獲取新的授權(quán)碼
3.OAuth授權(quán)模式:簡(jiǎn)化模式虏杰,密碼模式纺阔,客戶端模式
簡(jiǎn)化模式流程:
沒有后臺(tái)服務(wù)器笛钝,或不能妥善保管第三方密鑰情況下:
web-Hosted Client Resource:內(nèi)嵌到瀏覽器中的客戶端模塊
User-Agent:用戶代理玻靡,一般為瀏覽器
開始請(qǐng)求部分與授權(quán)碼模式相同中贝,返回值為重定向url和令牌雄妥,認(rèn)證服務(wù)器將令牌放置在url的哈希值部分(#后面的部分)一般認(rèn)為是未知信息老厌,轉(zhuǎn)發(fā)到服務(wù)端哈希值會(huì)被忽略掉。
web資源模塊處理重定向url,返回給用戶代理一個(gè)腳本用于解析醋拧,用戶代理完成解析后丹壕,返回給客戶端令牌信息菌赖。
通常會(huì)將web-Hosted Client Resource部分內(nèi)嵌到Client琉用,直接截取收到的信息,提取令牌信息簡(jiǎn)化流程
簡(jiǎn)化模式請(qǐng)求參數(shù):
簡(jiǎn)化模式請(qǐng)求與返回值:
沒有刷新令牌的原因:不能妥善保管第三方密鑰,有刷新令牌降低安全性
密碼模式請(qǐng)求流程:
用戶需要將用戶名與密碼告訴客戶端黍氮,但客戶端不得存儲(chǔ)密碼
用戶對(duì)客戶端足夠的信任沫浆,認(rèn)證服務(wù)器沒有其他的認(rèn)證方式可以選擇時(shí)采用件缸。
密碼模式請(qǐng)求參數(shù):
密碼模式請(qǐng)求具體內(nèi)容:
密碼模式請(qǐng)求返回值:
密碼模式請(qǐng)求返回值與授權(quán)碼模式返回值類似
客戶端模式請(qǐng)求流程:
用戶在客戶端注冊(cè),客戶端提出請(qǐng)求痊末,授權(quán)不明顯
客戶端模式請(qǐng)求參數(shù):
客戶端模式請(qǐng)求具體內(nèi)容:
客戶端模式請(qǐng)求返回值:
客戶端模式的返回值與其他幾種認(rèn)證類型類似:
4.OAuth更新令牌與相關(guān)問題:
更新令牌的方法:
1.重復(fù)一遍認(rèn)證流程嚼吞,用戶手動(dòng)輸入用戶名密碼,發(fā)起請(qǐng)求認(rèn)證
2.使用refreshtoken獲取一個(gè)新的令牌炒刁,即刷新令牌操作
更新令牌參數(shù):
更新令牌具體請(qǐng)求過程:
4.1授權(quán)碼模式中請(qǐng)求參數(shù)state的作用:
當(dāng)多個(gè)用戶發(fā)起請(qǐng)求時(shí),如果沒有state參數(shù)城瞎,認(rèn)證服務(wù)器只會(huì)返回臨時(shí)授權(quán)碼這一個(gè)參數(shù)脖镀,容易混淆爷贫。添加state參數(shù)可以將發(fā)起請(qǐng)求的的用戶與獲得的臨時(shí)授權(quán)碼一一對(duì)應(yīng)漫萄。對(duì)應(yīng)方式不可預(yù)期以提高安全性腾务。
4.2為什么需要臨時(shí)授權(quán)這一過程:
(1)redirect_url的安全性
redirect_url由第三方提供,是一個(gè)可訪問的server表單地址未巫。如果被截獲叙凡,令牌會(huì)被截獲
(2)redirect_url不如access token敏感握爷,被截獲不會(huì)泄漏用戶的資源信息严里。
(3)如果沒有臨時(shí)授權(quán)碼這一步刹碾,需要增加整個(gè)認(rèn)證過程中的安全性
4.3 申請(qǐng)百度開發(fā)者賬號(hào)以及百度OAuth
http://developer.baidu.com/wiki/index.php?title=docs/oauth
4.4獲取百度令牌
http://developer.baidu.com/wiki/index.php?title=docs/oauth/authorization
4.5獲取百度用戶信息
二迷帜、android工程中獲取百度令牌信息
http://developer.baidu.com/wiki/index.php?title=docs/oauth/showcase
下載安卓相關(guān)的sdk戏锹,解壓后將其中的 jar包導(dǎo)入工程景用。
Project Structure->添加app的dependencies,添加百度相關(guān)的jar包
創(chuàng)建Baidu對(duì)象割粮,調(diào)用authorize方法舀瓢,第四個(gè)參數(shù)新建百度對(duì)話框監(jiān)聽器對(duì)象京髓,實(shí)現(xiàn)其完成,異常芥玉,錯(cuò)誤灿巧,取消四個(gè)方法.
//第一個(gè)參數(shù)為clientId抠藕,即API Key
finalBaidu baidu =newBaidu("PRheS6ajilCjg1muyFDGeCYz",this);
baidu.authorize(this, true, true, newBaiduDialog.BaiduDialogListener() {
@Override
public voidonComplete(Bundle bundle) {
//獲取baidu對(duì)象中的AccessToken
refreshUI(baidu.getAccessToken());
}
@Override
public voidonBaiduException(BaiduException e) {
refreshUI("exception");
}
@Override
public voidonError(BaiduDialogError baiduDialogError) {
refreshUI("error");
}
@Override
public voidonCancel() {
refreshUI("cancel");
}
});
在主線程中盾似,創(chuàng)建私有方法雪标,用以刷新ui
private voidrefreshUI(finalString msg){
runOnUiThread(newRunnable() {
@Override
public voidrun() {
tvAccessToken.setText(msg);
}
內(nèi)部類中只能調(diào)用外部類的final對(duì)象
三汰聋、android工程中獲取百度個(gè)人信息
由于網(wǎng)絡(luò)請(qǐng)求不能放在主線程中烹困,所以通過以下兩種方式實(shí)現(xiàn):
1.在主線程中新建線程髓梅,使用百度提供的api,調(diào)用Baidu的對(duì)象的request方法返回json文本
啟動(dòng)線程
newThread(){
@Override
public voidrun() {
String url="https://openapi.baidu.com/rest/2.0/passport/users/getInfo";
try{
//使用baidu對(duì)象request時(shí)枯饿,第二個(gè)參數(shù)會(huì)自動(dòng)將包含在對(duì)象中的access Token傳入
finalString jsonText =mBaidu.request(url,null,"GET");
//返回對(duì)象為簡(jiǎn)單類(實(shí)體時(shí))時(shí)奢方,使用class型
finalUserEntity user =mGson.fromJson(jsonText,UserEntity.class);
//返回對(duì)象為泛型時(shí),使用Type方式
finalUserEntity user =mGson.fromJson(jsonText,newTypeToken(){}.getType());
//在主線程中實(shí)現(xiàn)runnable接口蟋字,完成ui的更新
runOnUiThread(newRunnable() {
@Override
public voidrun() {
tvResult.setText(jsonText);
tvUser.setText(mGson.toJson(user));
}
});
}catch(IOException e) {
e.printStackTrace();
}catch(BaiduException e) {
e.printStackTrace();
}
super.run();
}
}.start();
其中通過使用Gson庫(kù)苛聘,完成json文本到j(luò)son實(shí)體的轉(zhuǎn)換或json實(shí)體到j(luò)son文本的轉(zhuǎn)換
首先實(shí)體化Gson對(duì)象
mGson=newGson();