先來簡單介紹一下OAuth受權協議:OAUTH協議爲用戶資源的受權提供了一個安全的、開放而又簡易的標準。同時,任何第三方均可以使用OAuth認證服務,任何服務提供商均可以實現自身的OAuth認證服務,於是OAUTH是開放的。業界提供了OAuth的多種實現如 PHP,JavaScript,Java,Ruby等各類語言開發包,大大節約了程序員的時間,於是OAuth是簡易的。目前互聯網不少服務如Open API,不少大頭公司如Google,Yahoo,Microsoft等都提供了OAuth認證服務,這些都足以說明OAUTH標準逐漸成爲開放資源受權 的標準。 java
你所開發的應用須要流程以下:
1. 嚮應用服務商也就是服務提供商(QQ、新浪、搜狐等微博)請求request_token。
2. 獲得request_token後重定向用戶到服務商的受權頁面。
3. 若是用戶選擇受權你的應用,用request_token向服務商請求換取access_token。
4. 獲得access_token等信息訪問受限資源。
而服務商相應的響應以下:
1. 建立request_token返回給應用。
2. 詢問用戶是否受權此應用。若是用戶受權重定向用戶至應用頁面。
3. 建立access_token並返回給應用。
4. 響應受限資源請求並返回相關信息。
通俗點的說法就是「你拿着你得身份證實(request_token)向服務商申請進入用戶家的門鑰匙(access_token),服務商詢問用戶同不一樣意,若是用戶贊成服務商就給你進入用戶家門的鑰匙(access_token),拿到鑰匙後你就能夠進到用戶家裏」。 程序員
做爲一個開放協議目前有不少現成的Oauth庫可供開發者使用,能夠點擊這裏下載。不過有精力有時間的話仍是本身去實現一下OAuth受權的流程,能夠很好的體會OAuth認證協議的原理。
下面就是我使用Java實現Oauth的具體步驟:
1、獲取Request_token
首先得準備一下參數及其來源:
1. oauth_consumer_key —— 註冊應用後由應用服務商提供
2. consumer_secret —— 註冊應用後由應用服務商提供
3. oauth_callback —— 用戶受權後的返回地址
4. oauth_nonce —— 隨機字符串,須保證每次都不一樣
5. oauth_timestamp —— 時間戳
6. oauth_signature_method —— 簽名base string 的方法,目前支持 HMAC-SHA1
7. oauth_version —— Oauth協議版本
還須要下面三個請求地址(這些地址任何一個提供OAuth的服務商都會提供給你,看下API文檔就會找到):
1. requst_token_url —— 上面第1步中的請求地址
2. authorize_url —— 上面第2步的請求地址
3. 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 是請求的時間戳,個人代碼以下:
json
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部分
1. POST(也能夠是GET,取決於你應用服務商支持哪一個)。
2. Urlencode以後的requst_token_url 。
3. oauth_callback=Urlencode以後你的oauth_callback(Urlencode的參數爲「utf-8」)。
4. oauth_consumer_key = 你的oauth_consumer_key
5. oauth_nonce = 你的oauth_nonce
6. oauth_signature_method = 你的 oauth_signature_method
7. oauth_timestamp = 你的oauth_timestamp
8. oauth_version = 「1.0」——目前大多數OAuth都採用的是1.0或1.0a版本。
需 要注意的是上面除了1跟2外其餘參數的格數形如: abc=「abc」 ,而後先將上面1和2部分用&號相連獲得串A、3-8部分用&相連獲得串B,下面須要將串B再進行一次Urlencode獲得串C,最後 將A跟C以&號相連就獲得了base string。這個過程當中 oauth_callback 實質上通過了兩次 Urlencode ,組裝base string是很是容易出錯的,一不當心丟一個引號或者格式稍有不對就會出錯。
下面是個人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後加一個&號,簽名算法代碼以下:
app
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參數方式:
1. httpheader中
2. url中
3. post form中
國內各大微博的支持狀況是:新浪Httpheader可用,網易Httpheader可用,騰訊只支持在url,搜狐因爲沒有appkey因此還沒去嘗試。
若是使用Httpheader傳遞參數頭名爲「Authorization」,值爲下面的格式,將值改成本身應用的。 dom
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兩種方式的參數名和參數值也即上面的,徹底同樣。
請求發送成功後就會獲得的響應以下:
post
oauth_token=8ldIZyxQeVrFZXFOZH5tAwj6vzJYuLQpl0WUEYtWc& oauth_token_secret=x6qpRnlEmW9JbQn4PQVVeVG8ZLPEx6A0TOebgwcuA& oauth_callback_confirmed=true
能夠看到響應裏面已經包含oauth_token和oauth_token_secret了。url