Google Play服務在2.2以上裝置的發布在全球範圍內已經完成,所有這些裝置現在在OAuth 2.0下有了新的工具可以使用。下面是一個靈活性方面的例子,這種靈活性可以延伸Google Play服務支援的平台特性。
為什麼是OAuth 2.0
網上已經有很多使用者名稱和密碼了,而且密碼的強度良莠不齊,進一步說,你的裝置肯定能分辨出你是誰,這種情況下,業界一直認為,在缺乏高強度安全密碼 保護的前提下,OAuth 2.0是提供有效安全保障的最佳選擇之一。Google Play服務使需要訪問Google APIs的Android應用也可以使用OAuth 2.0,並且有很好的使用者體驗和安全性。
一般來說,當你的Android應用需要使用Google賬戶去訪問一些東西的時候,你得選擇用這個裝置上的哪個賬戶去訪問,然後必鬚生成一個OAuth2.0的令牌,用這個令牌在基於Http的對話方塊中和資源提供者互動。
如果使用最近為java發布的Google APIs用戶端檔案庫的話,這些任務很大程度上可以自動完成。這裡我們要討論的是你是否直接存取伺服器,比如在發送HTTP get和post請求到一個RESTful 的介面。
準備工作
Google Play服務儘管已經開始對外發布,但在發布之後也僅限於2.2及以上版本,大部分機子已經可以使用了,但仍有少量機子不可以。也有可能使用者選擇自己關掉服務。
因為這些原因,在你開始調用前,必須確認Google Play的服務已經安裝,調用isGooglePlayServicesAvailable()可以去確認,如何處理返回結果,在ConnectionResult這個類中有描述。
選擇一個賬戶
這不是也永遠不會是複雜困難的事,這兒有許多線上的例子,可以從Android賬戶管理器獲得賬戶和顯示許多種挑選清單。問題是它們有自己的外觀介面和一些類似的東西,比如安全問題。使用者有權期待系統上的一致性。
現在你可以使用 AccountPicker.newChooseAccountIntent()這 個方法獲得一個Intent,將其傳給startActivityForResult()會啟動一個標準的良好的使用者體驗介面,如果使用者願意的話會返回給 你一個賬戶。有兩點要注意:第一,當使用這些APIs時,需要使用一個Google賬戶(AccountManager可以處理多個賬戶),所以指定 GoogleAuthUtil.GOOGLE_ACCOUNT_TYPE的值作為 allowableAccountTypes參數的值。第二,你不需要一個android.accounts.Account對象,只需要email地址就可以,它可以唯一確定一個google賬戶。
擷取Token
你能在一次調用中提供多個用空格分開的scop這裡只需要調用一個方法:GoogleAuthUtil.getToken(), 它需要3個參數:Context,email地址,和另一個叫著scope的字串變數。每一個和oauth2.0對話的資訊源需要公布它使用的域 (scope),比如,訪問Google+的api,需要的scope是e,能得到一個可以訪問所有那些scope的令牌(token)。下面就是很典型 的代碼:
View Code
1 private final static String G_PLUS_SCOPE="oauth2:https://www.googleapis.com/auth/plus.me";2 3 private final static String USERINFO_SCOPE = "https://www.googleapis.com/auth/userinfo.profile";4 5 private final static String SCOPES = G_PLUS_SCOPE + " " + USERINFO_SCOPE;
在理想的情況下,getToken()將會是同步的,但有3件事會讓其變得不那麼簡單:
- 應用第一次請求token訪問資源時,系統會和使用者互動,詢問使用者是否允許。
- 每次請求token時,系統會和同一個後台伺服器有網路會話。
- 處理請求的裝置可能會過載而不能立馬給你token,它不會讓你等或者告訴你請求失敗,而會告知你先離開一會兒再回來。
顯然,你絕對不能在UI線程中調用getToken(),因為那會導致不可預知的延遲。
當你調用getToken()時,會發生以下的事情:
如果成功返回token,那說明各個步驟都是對的,後台認為認證是成功的,接著你處理和使用token就可以了。
拋出UserRecoverableAuthException異常意味著你需要和使用者互動,很可能是要求使用者使用賬戶進行認證。異常有一個getIntent()方法,你可以將其傳回值傳給startActivityForResult()來搞定。當然你需要注意onActivityResult()是否ok。
拋出IOException時,說明證明伺服器很忙,後者有網路異常(在行動裝置上這個情況經常出現)。你不應該馬上就放棄,因為再試一次可能就好了。換句話說,如果你立馬返回並再次向伺服器提出請求,結果不見得好。所以你需要等一下。最好的處理辦法是指數退避模式。
拋出GoogleAuthException,意味著認證無法通過,你該禮貌地讓你的使用者冷靜下來。如果請求的scope非法或者email地址對應的賬戶在當前裝置上不存在的話就會發生這種異常。
下面是一些範例程式碼:
View Code
1 try { 2 // if this returns, the OAuth framework thinks the token should be usable 3 String token = GoogleAuthUtil.getToken(this, mRequest.email(), 4 mRequest.scope()); 5 response = doGet(token, this); 6 7 }catch (UserRecoverableAuthException userAuthEx) { 8 // This means that the app hasn't been authorized by the user for access 9 // to the scope, so we're going to have to fire off the (provided) Intent10 // to arrange for that. But we only want to do this once. Multiple11 // attempts probably mean the user said no.12 if (!mSecondTry) {13 startActivityForResult(userAuthEx.getIntent(), REQUEST_CODE);14 response = null;15 } else {16 response = new Response(-1, null, "Multiple approval attempts");17 }18 19 }catch (IOException ioEx) {20 // Something is stressed out; the auth servers are by definition21 // high-traffic and you can't count on 100% success. But it would be22 // bad to retry instantly, so back off23 if (backoff.shouldRetry()) {24 backoff.backoff();25 response = authenticateAndGo(backoff);26 } else {27 response = new Response(-1, null, "No response from authorization server.");28 }29 }catch (GoogleAuthException fatalAuthEx) {30 Log.d(TAG, "Fatal Authorization Exception");31 response = new Response(-1, null, "Fatal authorization exception: " +32 fatalAuthEx.getLocalizedMessage());33 }
這是一個我已經提交到code.google.com上的一個用AuthorizedActivity類實現了的樣本庫。我們 覺得這種認證行為將會是不同應用的特定行為,所以這個AuthorizedActivity類不見得對每個人都有用,但它是基於Apach2許可證,你可 以在你需要的地方隨便用。它已作為一個工程建立了起來,這裡有一個叫做G+ Snowflake的應用,它用那個建好的工程取得了許多你在google+上的提交的東西。這個應用在google play上有,源碼也線上上。
註冊你的應用
大部分進行oauth2.0認證的伺服器都要你進行app註冊,當然google的也不例外。訪問 Google APIs Console, 建立一個工程,把你要訪問的apis從服務菜單中揀出來,然後點擊訪問API的標籤進行註冊。輸入你應用的報名,即在 AndroidManifest.xml中package屬性對應的值,另外需要你應用的SHA1碼。任何在google play 發布過應用的人都知道秘鑰和簽名。但在這之前你會得到一個debug版本的應用,進行這種認證的工具在~/.android /debug.keystore,密碼是android。幸運的是,你的電腦很可能已經裝了keytool這個程式,你能用它來產生你的簽名,對於 debug版本,產生簽名的命令是:
keytool -exportcert -alias androiddebugkey -keystore ~/.android/debug.keystore -v -list
這就能產生SHA1簽名,很容易剪下粘貼滴哦。
這方法可能讓人覺得有點陳舊,但卻值得這麼做,因為戲法就是這麼發生的。當你的應用被註冊過,然後你產生一個token並將其發送給服務提供者,服
務提供者通過google檢測token是否正確,token是google發布了的,並且google提供給你應用的包名。之前你們做過這件事的傢伙們
可能想要知道Client IDs和API Keys了,但在這種機制下,你們並不需要它們。
使用你的Token
假設你已經註冊過你的應用並調用GoogleAuthUtil.getToken()得到了一個token,假如它就是“MissassaugaParnassus42”。然後你需要做的是,當你向服務提供者發送一個HTTP請求時,包括一個像這樣的HTTP要求標頭:
然後你的HTTP GETs和POSTs開始工作了,你應該調用GoogleAuthUtil.getToken()在每次 GETs 或者 POSTs請求前獲得一個token。在恰當的時候快取資料還有處理token的到期和重新整理,這些事情都不用你操心的。
再說一遍,如我上面說的,如果你用著為java而存在的google apis用戶端很舒服,它將會為你處理所有用戶端的事情,你需要做的就是去註冊一下而已。
另外,在這裡會有一些編碼投入,但回報是巨大的:安全性,認證通過,已授權,擁有良好使用者體驗的服務訪問。
英文原文:Google Data 編譯:ImportNew - 牛秦勇
譯文地址: http://www.importnew.com/949.html