本篇說說關於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;
}
}
這樣就完成了OAuth功能類的開發,後面都會用到這個類相關的方法。本篇到這裡就算是完結請繼續關注後面的文章。