Thursday, December 22, 2011

淺談OAuth in Android -- 以Plurk為例子

OAuth是目前比較熱門的認證機制之一,他有個最大的好處就在於完全不需要在client端輸入賬號密碼,這部分完全會由web端完成。不過,他機制非常的複雜,有些地方做的讓人覺得很龜毛,所以我們在這篇只要淺談就好,其他的部分我會介紹一個函式庫來把它完成。

這邊有一篇非常不錯的OAuth機制介紹,有興趣的朋友可以看看。太細節部分的工作原理我們就不涉足了,我們專心看看最基本的認證步驟

  1. app開發者跟網站註冊取得API Key跟API Secret
  2. 開始認證的時候,用這組key/secret/callback(*1)跟網站要一個Request Token(*2)
  3. 用這組Request Token, callback組合成一個網址,讓使用者進入該網址認證
  4. 認證成功以後會傳回一個oauth_verifier,通常是一個很好閱讀的字串或者數字
  5. app端把這組verifier,以及request key跟網站取得半永久性的Access Token(*2)
  6. 往後對這個網站任何要求(比方說,plurk來講,取得時間軸)使用這個Token即可,app把它存起來備用,就不需要重新跟網站申請認證了。

這幾個步驟其實相當的繁瑣,尤其是對網站要求每次都要做一個全面性的Parameter Sign的動作,裡面牽涉的東西對一個初學者來講真是煩人到爆炸。當然,就會有人會寫一組library來解決這問題:我們今天介紹的就是oauth-signpost library

基本的取得jar,放進project,設定buildpath這些基礎到爆的東西我們就不討論了。首先,我們要先去Plurk申請一組API Key來作為我們的開發用途。所以我們就有了API Key/Secret了。接下來,回到Plurk API介紹的頁面,他提供了幾個網址供OAuth使用。基本上這些分別是幹嘛的我們就不予深究了,我們只要知道她是要怎麼用。

signpost我們會用到根OAuth有關的一共有兩個部分:OAuthConsumer代表的是我們APP端的所有資料,包含Access Token等等(不過她好像沒幫你存,你要自己存),而OAuthProvider則是代表網站的OAuth認證部分。

static final String PLURK_REQUEST_URL = "http://www.plurk.com/OAuth/request_token";

static final String PLURK_AUTHORIZATION_URL = "http://www.plurk.com/m/authorize";

static final String PLURK_ACCESS_URL = "http://www.plurk.com/OAuth/access_token";

static final String PLURK_CALLBACK_URL = "myplurk:///";

static final String PLURK_CONSUMER_KEY = "你的API Key";

static final String PLURK_CONSUMER_SECRET = "你的API Secret";


我們先把這些東西設定變數,等等會用到。接下來我們設定Provider跟Consumer

mainConsumer = new DefaultOAuthConsumer(PLURK_CONSUMER_KEY, PLURK_CONSUMER_SECRET);

mainProvider = new DefaultOAuthProvider(PLURK_REQUEST_URL, PLURK_ACCESS_URL, PLURK_AUTHORIZATION_URL);

ok,那所有東西差不多就完成了。我們要讓使用者認證的時候,只要開一個url,載入provider提供的url :

String url = mainProvider.retrieveRequestToken(mainConsumer, PLURK_CALLBACK_URL);

利用webview打開這個以後,把webview設定一個WebViewClient,然後override它的link click

private class AuthClient extends WebViewClient {

@Override

public void onPageStarted(WebView view, String url, Bitmap favicon) {

super.onPageStarted(view, url, favicon);

}

@Override

public void onPageFinished(WebView view, String url) {

super.onPageFinished(view, url);

}

@Override

public boolean shouldOverrideUrlLoading(WebView view, String urlString) {

Log.d("SubPlurkV2", "url : " + urlString);

if(urlString.contains("subplurkv2")) {

Uri url = Uri.parse(urlString);

String verifier = url.getQueryParameter("oauth_verifier");

try {

SystemManager.getInst().getAuthManager().aquireAccessToken(verifier);

} catch (Exception e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

finish();

}

return super.shouldOverrideUrlLoading(view, urlString);

}

然後我們可以取得verifier,利用這個取得Access Token

mainProvider.retrieveAccessToken(mainConsumer, verifier);

Log.d("SubPlurkV2", "Token = " + mainConsumer.getToken() + " and secret = " + mainConsumer.getTokenSecret());


把這祖Token記錄起來,以後會用到。最後,我們來試試看最簡單地拿取時間軸吧

mainConsumer.setAccessToken("U5GNYyH6wVGS", "aCtJ9XVgNTeIpigq3qxsLi70Sv0HbA6h");


 

URL url = new URL("http://www.plurk.com/APP/Timeline/getPlurks");

HttpURLConnection request = (HttpURLConnection) url.openConnection();

request.setDoOutput(true);

request.setRequestMethod("POST");

mainConsumer.sign(request);

request.connect();

String context = StreamUtil.InputStreamToString(request.getInputStream());

Log.d("SubPlurkV2", "" + context);


have fun! 參考plunk api list繼續實做其他的api吧!