Android新浪微網誌OAuth授權認證用戶端圖如下:
下面再來說說:關于新浪微網誌OAuth授權認證
新浪開放api都必須在這個基礎上才能調用,是以有必要專門來講講,前面的文章中已經提到過關于新浪微網誌提供了OAuth和Base OAuth兩種認證方式,并且本項目采用OAuth認證方式,至于為什麼采用這個OAuth認證而不采用Base OAuth認證原因很簡單,自從Twitter隻支援OAuth認證方式以來,各大應用都紛紛轉向OAuth認證方式,而新浪微網誌的開放平台也将在近日停止Base OAuth的認證方式。
OAuth的基本概念,OAUTH協定為使用者資源的授權提供了一個安全的、開放而又簡易的标準。與以往的授權方式不同之處是OAUTH的授權不會使第三方觸及到使用者的帳号資訊(如使用者名與密碼),即第三方無需使用使用者的使用者名與密碼就可以申請獲得該使用者資源的授權,是以OAUTH是安全的。同樣新浪微網誌提供OAuth認證也是為了保證使用者賬号和密碼的安全,在這裡通過OAuth建立普通新浪微網誌使用者、用戶端程式(我們正在開發的這個android用戶端程式)、新浪微網誌三者之間的互相信任關系,讓用戶端程式(我們正在開發的這個android用戶端程式)不需要知道使用者的賬号和密碼也能浏覽、釋出微網誌,這樣有效的保護了使用者賬号的安全性不需要把賬号密碼透露給用戶端程式又達到了通過用戶端程式寫微網誌看微網誌目的。這個是OAuth的作用。
結合新浪微網誌的OAuth認證來說說具體的功能實作,首先羅列一下關鍵字組,下面四組關鍵字跟我們接下來OAuth認證有非常大的關系。
第一組:(App Key和App Secret),這組參數就是本系列文本第一篇提到的建一個新的應用擷取App Key和App Secret。
第二組:(Request Token和Request Secret)
第三組:(oauth_verifier)
第四組:(user_id、Access Token和Access Secret)
新浪微網誌的OAuth認證過程,當使用者第一次使用本用戶端軟體時,用戶端程式用第一組作為參數向新浪微網誌發起請求,然後新浪微網誌經過驗證後傳回第二組參數給用戶端軟體同時表示新浪微網誌信任本用戶端軟體,當用戶端軟體擷取第二組參數時作為參數引導使用者浏覽器跳至新浪微網誌的授權頁面,然後使用者在新浪的這個授權頁面裡輸入自己的微網誌賬号和密碼進行授權,完成授權後根據用戶端設定的回調位址把第三組參數傳回給用戶端軟體并表示使用者也信任本用戶端軟體,接下用戶端軟體把第二組參數和第三組參數作為參數再次向新浪微網誌發起請求,然後新浪微網誌傳回第四組參數給用戶端軟體,第四組參數需要好好的儲存起來這個就是用來代替使用者的新浪賬号和密碼用的,在後面調用api時都需要。從這個過程來看使用者隻是在新浪微網誌的認證網頁輸入過賬戶和密碼并沒有在用戶端軟體裡輸入過賬戶和密碼,用戶端軟體隻儲存了第四組資料并沒有儲存使用者的賬戶和密碼,這樣有效的避免了賬戶和密碼透露給新浪微網誌之外的第三方應用程式,保證 了安全性。
本項目用為了友善開發采用了oauth-signpost開源項目進行OAuth認證開發,建立OAuth.java類檔案對OA進行簡單的封裝,OAuth類主要有RequestAccessToken、GetAccessToken、SignRequest三個方法,第一個方法RequestAccessToken就是上面過程中用來擷取第三組參數用的,GetAccessToken方法是用來擷取第四組參數用,SignRequest方法是用來調用api用。由于采用了oauth-signpost開源項目簡單了很多。具體代碼如下:
public class OAuth {
private CommonsHttpOAuthConsumer httpOauthConsumer;
private OAuthProvider httpOauthprovider;
public String consumerKey;
public String consumerSecret;
public OAuth()
{
// 第一組:(App Key和App Secret)
// 這組參數就是本系列文本第一篇提到的建一個新的應用擷取App Key和App Secret。
this("3315495489","e2731e7grf592c0fd7fea32406f86e1b");
}
public OAuth(String consumerKey,String consumerSecret)
{
this.consumerKey=consumerKey;
this.consumerSecret=consumerSecret;
}
public Boolean RequestAccessToken(Activity activity,String callBackUrl){
Boolean ret=false;
try{
httpOauthConsumer = new CommonsHttpOAuthConsumer(consumerKey,consumerSecret);
httpOauthprovider = new DefaultOAuthProvider("http://api.t.sina.com.cn/oauth/request_token","http://api.t.sina.com.cn/oauth/access_token","http://api.t.sina.com.cn/oauth/authorize");
String authUrl = httpOauthprovider.retrieveRequestToken(httpOauthConsumer, callBackUrl);
activity.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(authUrl)));
ret=true;
}catch(Exception e){
}
return ret;
}
public UserInfo GetAccessToken(Intent intent){
UserInfo user=null;
Uri uri = intent.getData();
String verifier = uri.getQueryParameter(oauth.signpost.OAuth.OAUTH_VERIFIER);
try {
httpOauthprovider.setOAuth10a(true);
httpOauthprovider.retrieveAccessToken(httpOauthConsumer,verifier);
} catch (OAuthMessageSignerException ex) {
ex.printStackTrace();
} catch (OAuthNotAuthorizedException ex) {
ex.printStackTrace();
} catch (OAuthExpectationFailedException ex) {
ex.printStackTrace();
} catch (OAuthCommunicationException ex) {
ex.printStackTrace();
}
SortedSet<String> user_id= httpOauthprovider.getResponseParameters().get("user_id");
String userId=user_id.first();
String userKey = httpOauthConsumer.getToken();
String userSecret = httpOauthConsumer.getTokenSecret();
user=new UserInfo();
user.setUserId(userId);
user.setToken(userKey);
user.setTokenSecret(userSecret);
return user;
}
public HttpResponse SignRequest(String token,String tokenSecret,String url,List params)
{
HttpPost post = new HttpPost(url);
//HttpClient httpClient = null;
try{
post.setEntity(new UrlEncodedFormEntity(params,HTTP.UTF_8));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
//關閉Expect:100-Continue握手
//100-Continue握手需謹慎使用,因為遇到不支援HTTP/1.1協定的伺服器或者代理時會引起問題
post.getParams().setBooleanParameter(CoreProtocolPNames.USE_EXPECT_CONTINUE, false);
return SignRequest(token,tokenSecret,post);
}
public HttpResponse SignRequest(String token,String tokenSecret,HttpPost post){
httpOauthConsumer = new CommonsHttpOAuthConsumer(consumerKey,consumerSecret);
httpOauthConsumer.setTokenWithSecret(token,tokenSecret);
HttpResponse response = null;
try {
httpOauthConsumer.sign(post);
} catch (OAuthMessageSignerException e) {
e.printStackTrace();
} catch (OAuthExpectationFailedException e) {
e.printStackTrace();
} catch (OAuthCommunicationException e) {
e.printStackTrace();
}
//取得HTTP response
try {
response = new DefaultHttpClient().execute(post);
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return response;
}
}