OAuth授權的Java實現詳解
由于最近在開發一個關于微博整合的小應用,于是開始接觸各大微博平臺的開放平臺(新浪、搜狐、網易、QQ):目前這三大微博的應用開發都采用OAuth授權,要訪問大部分API都需要OAuth方式的身份鑒權。
OAuth是什么?
先 來簡單介紹一下OAuth授權協議:OAUTH協議為用戶資源的授權提供了一個安全的、開放而又簡易的標準。同時,任何第三方都可以使用OAuth認證服 務,任何服務提供商都可以實現自身的OAuth認證服務,因而OAUTH是開放的。業界提供了OAuth的多種實現如 PHP,JavaScript,Java,Ruby等各種語言開發包,大大節約了程序員的時間,因而OAuth是簡易的。目前互聯網很多服務如Open API,很多大頭公司如Google,Yahoo,Microsoft等都提供了OAuth認證服務,這些都足以說明OAUTH標準逐漸成為開放資源授權 的標準。
OAuth的授權流程
你所開發的應用需要流程如下:
- 向應用服務商(新浪、搜狐等微博)請求request_token。
- 得到request_token后重定向用戶到服務商的授權頁面。
- 如果用戶選擇授權你得應用,用request_token向服務商請求換取access_token。
- 得到access_token等信息訪問受限資源。
而服務商相應的響應如下:
- 創建request_token返回給應用。
- 詢問用戶是否授權此應用。如果用戶授權重定向用戶至應用頁面。
- 創建access_token并返回給應用。
- 響應受限資源請求并返回相關信息。
通俗點的說法就是“你拿著你得身份證明(request_token)向服務商申請進入用戶家的門鑰匙(access_token),服務商詢問用戶同不同意,如果用戶同意服務商就給你進入用戶家門的鑰匙(access_token),拿到鑰匙后你就可以進到用戶家里”。
OAuth授權的Java實現
作為一個開放協議目前有很多現成的Oauth庫可供開發者使用,可以點擊這里下載。不過有精力有時間的話還是自己去實現一下OAuth授權的流程,可以很好的體會OAuth認證協議的原理。
下面就是我使用Java實現Oauth的具體步驟:
一、獲取Request_token
首先得準備一下參數及其來源:
- oauth_consumer_key —— 注冊應用后由應用服務商提供
- consumer_secret —— 注冊應用后由應用服務商提供
- oauth_callback —— 用戶授權后的返回地址
- oauth_nonce —— 隨機字符串,須保證每次都不同
- oauth_timestamp —— 時間戳
- oauth_signature_method —— 簽名base string 的方法,目前支持 HMAC-SHA1
- oauth_version —— Oauth協議版本
還需要下面三個請求地址(這些地址任何一個提供OAuth的服務商都會提供給你,看下API文檔就會找到):
- requst_token_url —— 上面第1步中的請求地址
- authorize_url —— 上面第2步的請求地址
- access_token_url —— 上面第3步的請求地址
至于如何注冊應用,新浪微博點此,網易微博點此,騰訊微博點此,搜狐微博需要你發郵件索取,具體看這里。注冊成功后就會獲得oauth_consumer_key 和 consumer_secret 兩個參數。
oauth_callback 起的作用是當用戶授權成功后服務商會把用戶重定向到這個網址。
oauth_nonce 是一個隨機字符串下面是我的生成代碼:
public String set_nonce() {
String base = "abcdefghijklmnopqrstuvwxyz0123456789";
Random random = new Random();
StringBuffer sb = new StringBuffer();
for (int i = 0; i < 18; i++) {
int number = random.nextInt(base.length());
sb.append(base.charAt(number));
}
return sb.toString();
}
oauth_timestamp 是請求的時間戳,我的代碼如下:
public String set_timestamp() {
Date date = new Date();
long time = date.getTime();
return (time + "").substring(0, 10);
}
需要說明一下的是這里的時間戳為10位而不是13位,因此截取0-10位置。
其他參數直接指定就行了。
接下來,有了這些參數就可以組裝base string了。貯備base string的目的就是為了得到 oauth_signature 這個參數,這個參數向服務商發送請求的時候需要用到。
組裝的方法是用下面8部分
- POST(也可以是GET,取決于你應用服務商支持哪個)。
- Urlencode之后的requst_token_url 。
- oauth_callback=Urlencode之后你的oauth_callback(Urlencode的參數為“utf-8”)。
- oauth_consumer_key = 你的oauth_consumer_key
- oauth_nonce = 你的oauth_nonce
- oauth_signature_method = 你的 oauth_signature_method
- oauth_timestamp = 你的oauth_timestamp
- oauth_version = “1.0”——目前大多數OAuth都采用的是1.0或1.0a版本。
下面是我的Java實現代碼:
public String set_basestring() throws UnsupportedEncodingException {
String bss;
bss = oauth_request_method + "&"
+ URLEncoder.encode(requst_token_url, "utf-8") + "&";
String bsss = "oauth_callback="
+ URLEncoder.encode(oauth_callback, "utf-8")
+ "&oauth_consumer_key=" + oauth_consumer_key + "&oauth_nonce="
+ oauth_nonce + "&oauth_signature_method="
+ oauth_signature_method + "&oauth_timestamp="
+ oauth_timestamp + "&oauth_version=" + oauth_version;
bsss = URLEncoder.encode(bsss, "utf-8");
return bss + bsss;
}
有 了base string就可以簽名生成oauth_signature這個參數,oauth_signature會在請求request_token的時候用到。簽 名算法是HMAC-SHA1,簽名的key就是最開始的consumer_secret后加一個&號,簽名算法代碼如下:
public String hmacsha1(String data, String key) {
byte[] byteHMAC = null;
try {
Mac mac = Mac.getInstance("HmacSHA1");
SecretKeySpec spec = new SecretKeySpec(key.getBytes(), "HmacSHA1");
mac.init(spec);
byteHMAC = mac.doFinal(data.getBytes());
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException ignore) {
}
String oauth = new BASE64Encoder().encode(byteHMAC);
return oauth;
}
里面用的的BASE64Encoder這個類可以Google一個。
得到oauth_signature后就要開始向 requst_token_url 發送請求了,OAuth規范定義了三種傳遞OAuth參數方式:
- httpheader中
- url中
- post form中
國內各大微博的支持情況是:新浪Httpheader可用,網易Httpheader可用,騰訊只支持在url,搜狐由于沒有appkey所以還沒去嘗試。
如果使用Httpheader傳遞參數頭名為“Authorization”,值為下面的格式,將值改為自己應用的。
OAuth oauth_nonce="9zWH6qe0qG7Lc1telCn7FhUbLyVdjEaL3MO5uHxn8", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1272323047", oauth_consumer_key="GDdmIQH6jhtmLUypg82g", oauth_token="8ldIZyxQeVrFZXFOZH5tAwj6vzJYuLQpl0WUEYtWc", oauth_verifier="pDNg57prOHapMbhv25RNf75lVRd6JDsni1AJJIDYoTY", oauth_signature="PUw%2FdHA4fnlJYM6RhXk5IU%2F0fCc%3D", oauth_version="1.0"
url和post form兩種方式的參數名和參數值也即上面的,完全一樣。
請求發送成功后就會得到的響應如下:
oauth_token=8ldIZyxQeVrFZXFOZH5tAwj6vzJYuLQpl0WUEYtWc&oauth_token_secret=x6qpRnlEmW9JbQn4PQVVeVG8ZLPEx6A0TOebgwcuA&oauth_callback_confirmed=true
可以看到響應里面已經包含oauth_token和oauth_token_secret了。
(未完)
http://www.littlear.com/post/2011/01/0285/