本文說明如何在 Flash 或 Silverlight 應用程式中使用 Google 的 AuthSub 驗證系統。
注意:如果您很熟悉 AuthSub (Google 的網頁式應用程式帳戶驗證服務),您會發現在 AuthSub 中實作 ActionScript 的概念其實很類似。基礎的實作方式並不相同,但差別在於您身為用戶端應用程式開發人員。在某些說明文件中,如果區別與無關緊要,那麼我們讓 ActionScript 的 AuthSub 簡稱為「AuthSub」。
AuthSub for ActionScript 介面可代表 Flash 或 Silverlight 應用程式代表使用者驗證受保護的 Google Data API 資訊提供。為了維持高安全性,此介面可讓應用程式取得驗證權杖,而無需處理使用者的帳戶登入資訊。
AuthSub for ActionScript 是 JavaScript 適用的 AuthSub 變體。和 JavaScript 的 AuthSub 一樣,它提供了跨網域的方法,讓用戶端應用程式能夠透過非 Google 網域代管的網頁進行驗證。和標準的 AuthSub 不同,驗證服務位於不同的網域 (accounts.googleapis.com,而非 www.google.com),且提供允許從外部網站存取該網域的 crossdomain.xml
檔案。
另請參閱 Google Accounts API 群組,瞭解如何使用所有的 Authentication 服務 API。
目標對象
本文件的適用對象為開發 Google 服務的 Flash 或 Silverlight 網路應用程式開發人員。
本文假設您已瞭解 Google Data API 通訊協定和 AuthSub 介面背後的一般概念。同時假設您知道如何在 ActionScript 中編寫程式。
支援的環境
Firefox 1.5 及更高版本以及 Internet Explorer 6.0 及更高版本目前支持 AuthSub for ActionScript,具有 Flash 9.0 或更高版本或 Silverlight 2.0 或更高版本。
適用於 AuthSub for ActionScript 的運作方式
以下簡單說明網路應用程式、Google 驗證服務和 Google 資料服務之間的通訊運作方式:
- 如要代表使用者存取 Google Data 服務,網頁應用程式必須具備有效的驗證權杖。應用程式通常會將這個憑證儲存在 Cookie 中;如果沒有,則網路應用程式必須透過 AuthSub 取得憑證。為取得憑證,網頁應用程式會呼叫 AuthSub 的 ActionScript 登入服務呼叫驗證服務,並指定要存取的服務。
- 驗證服務收到來自網路應用程式的要求時,「驗證」服務會將使用者重新導向至「存取要求」網頁。系統會提示使用者登入自己的 Google 帳戶,並要求使用者授予或拒絕 Google 服務的存取權。
- 使用者決定授予或拒絕網路應用程式的存取權限。使用者拒絕存取時,系統會將他們導向 Google 網頁,而不是返回網路應用程式。
- 如果使用者成功登入並授予存取權,「驗證」服務會將使用者重新導向回原本呼叫的網路應用程式網址。重新導向會透過查詢參數提供指定服務的驗證權杖。應用程式應將憑證儲存為使用者瀏覽器中的 Cookie,位於網路應用程式網域下。這個權杖在撤銷前仍然有效。(如要瞭解如何撤銷憑證,請參閱關於憑證一節)。
- 網路應用程式與 Google Data 服務聯絡,傳送驗證權杖和每項傳送至服務的要求。
- 如果 Google 資料服務識別了權杖,便會提供要求的資料。
使用 AuthSub for ActionScript 介面
AuthSub for ActionScript 或 AuthSubAS 為使用 Google Data API 的 Flash (或 Silverlight) 應用程式提供跨網域 AuthSub 端點。
AuthSubAS 提供 google.com 中 AuthSub 端點的鏡像,且額外提供 crossdomain.xml
檔案,允許 Flash (或 Silverlight) 存取這些端點。舉例來說,您可以透過存取 https://accounts.googleapis.com/accounts/AuthSubSessionToken,藉此使用 AuthSubSessionToken 端點。
下列步驟會說明如何取得驗證權杖,並使用該憑證從 Flash 應用程式存取 Google 服務。
- 設定跨網域政策。
如果要以跨網域方式使用 Flash,您必須針對要存取的每個外部網域,以政策初始化 Flash。方法是為每個網域叫用 ActionScript 方法
Security.loadPolicyFile(policy)
,如下所示:<?xml version="1.0" encoding="utf-8"?> <Application xmlns="http://www.adobe.com/2006/mxml" initialize="onInitialized()" applicationComplete="onLoaded()"> <Script> import flash.external.ExternalInterface; import flash.net.navigateToURL; import mx.controls.Alert; private function onInitialized() : void { // Load the cross domain policy file for each of the googleapis.com // domains used. At the very least, we need the ones for the API (photos, // in this case) and the one for AuthSub for ActionScript (accounts). Security.loadPolicyFile('http://photos.googleapis.com/data/crossdomain.xml'); Security.loadPolicyFile('https://accounts.googleapis.com/crossdomain.xml'); }
請注意,我們需要載入
accounts.googleapis.com
(AuthSubAS) 和photos.googleapis.com/data
(PicasaWeb 政策,稍後會存取此範例) 的政策。 - 要求一次性使用權杖。
在 AuthSub 程序中,第一步是向 AuthSub 端點要求一次性使用憑證。應用程式應對
AuthSubRequest
端點發出呼叫,以完成此動作,如下所示:var getTokenPage : URLRequest = new URLRequest('https://www.google.com/accounts/AuthSubRequest'); // Construct the parameters of the AuthSub request. These are the same parameters // as normal AuthSub, which can be found here: /accounts/docs/AuthSub.html#AuthSubRequest var authSubParams : URLVariables = new URLVariables(); authSubParams['scope'] = 'http://photos.googleapis.com/data'; // photos API authSubParams['session'] = 1; // single-use token authSubParams['secure'] = 0; // non-secure apps authSubParams['next'] = 'photos.swf'; // The URL of this app. getTokenPage.data = authSubParams; navigateToURL(getTokenPage, '_top');
這個方法需要 scope 值。每項 Google 服務都會定義其允許的存取權範圍,您必須在符記要求中參照該範圍。如要判斷要使用的範圍值,請參閱您想存取的 Google 服務說明文件。範圍看起來像是網址,可以是識別服務的簡單網址,也可以指定限制存取受限 (例如限制唯讀存取權)。當服務提供特定範圍選項時,請盡可能要求最嚴格的範圍。舉例來說,如要存取 Google 日曆的資料動態饋給,請使用
'http://www.google.com/calendar/feeds'
範圍,而不是'http://www.google.com/calendar'
。提示:
- 強烈建議您提供登入按鈕或其他使用者輸入機制,可提示使用者手動啟動登入程序。相反地,如果您在載入網頁後立即進行檢查並重新導向,不必等待使用者互動,那麼使用者在抵達網頁後,第一個看到的就是 Google 登入網頁。如果使用者決定不登入,Google 並不會將他們導回您的網頁;因此,從使用者的觀點來看,他們嘗試造訪您的網頁卻從不離開,但是並未送出。這種狀況可能會讓使用者感到困惑與不悅。
- 如果應用程式需要讓使用者存取多項 Google 服務,就必須為每個新服務要求一個新的憑證 (因為每項服務有不同的範圍)。
- 申請驗證權杖。
AuthSubRequest
端點會將使用者瀏覽器的網址設為http://yourWebAppUrl?token=singleUseToken
,藉此將單一使用權杖傳回您的應用程式。應用程式收到一次性使用憑證之後,必須針對多個用途 (長效) 權杖交換該權杖,才能用來對 Google 資料動態饋給發出請求。方法是使用單一使用權杖呼叫AuthSubSessionToken
方法。應用程式載入時,應檢查網址中是否有
token
參數:private function onLoaded() : void { // Once the application has loaded, check to see if an AuthSub token was
// placed into the current page's URL. If it was, the user has already
// authenticated, and we can continue to connect to the the service itself. var searchPortion : String = ExternalInterface.call('window.location.search.toString'); if (searchPortion.length > 0) { // remove the ? from the token and extract the token. searchPortion = searchPortion.substring(1); // NOTE: Real applications should parse the URL properly. if (searchPortion.indexOf('token=') == 0) { getLongLivedToken(searchPortion.substring(6)); return; } // more code ... }找到憑證後,應呼叫類似
getLongLivedToken
的方法,可叫用AuthSubSessionToken
端點:private function getLongLivedToken(singleUseToken : String) : void { // Construct a call to the AuthSub for ActionScript endpoint on accounts.googleapis.com. // This call will exchange the single use token given to use by AuthSub for a long-term // token that we can use to make requests to endpoints such as Photos. var getTokenRequest : URLRequest = new URLRequest('https://accounts.googleapis.com/accounts/AuthSubSessionToken'); // Due to a bug in Flash, a URLRequest with a GET request will // not properly send headers. We therefore use POST for this and *ALL* // requests. getTokenRequest.method = URLRequestMethod.POST; // Due to a bug in Flash, a URLRequest without a valid parameter will // not properly send headers. We therefore add a useless parameter to // make this code work. getTokenRequest.data = new URLVariables('pleaseignore=ignore'); // Add the AuthSub for ActionScript headers. getTokenRequest.requestHeaders.push(new URLRequestHeader('Authorization', 'AuthSub token="' + singleUseToken + '"')); // Create the loader to get the token itself. The loader will callback // to the following event handlers if and when the server responds. var getToken : URLLoader = new URLLoader(); getToken.addEventListener(Event.COMPLETE, onGetTokenResult); getToken.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onGetTokenFailed); getToken.addEventListener(IOErrorEvent.IO_ERROR, onGetTokenFailed); try { getToken.load(getTokenRequest); } catch (e : Error) { Alert.show('Some error occurred: ' + e); }
onGetTokenResult
處理常式等方法應該儲存傳回的權杖:private function onGetTokenResult(e : Event) : void { // Load the parameters from the response. var getToken : URLLoader = URLLoader(e.target); var params : URLVariables = new URLVariables(getToken.data); // Parse the session token from the result. Real applications // might at this point store the token in a long-term cookie so // that repeated usages of the application do not require this entire // authentication process. sessionToken = params.Token; // Trim the newline from the end of the session token. sessionToken = sessionToken.substring(0, sessionToken.length - 1); }
提示:
- 強烈建議您將應用程式的「長期」憑證儲存在 Cookie 中,並在進行定期權杖檢查前進行檢查;這樣使用者就不必在每次使用您的應用程式時造訪 AuthSub 確認網頁。
- 使用驗證權杖。
如要使用驗證權杖,請透過
Authorization
標頭附加在向 Google 服務發出的任何要求:Authorization: AuthSub token="(session token goes here)"
「相簿」服務的 ActionScript 範例:
// Prepare a request to the photos API for the private album // of the user. var albumRequest : URLRequest = new URLRequest('http://photos.googleapis.com/data/feed/api/user/default'); albumRequest.data = new URLVariables('access=private&v=2&err=xml'); // Due to a bug in Flash, a URLRequest with a GET request will // not properly send headers. We therefore use POST for this and *ALL* // requests. albumRequest.method = URLRequestMethod.POST; var authsubHeader : String = 'AuthSub token="' + sessionToken + '"'; // Add the Authorization header which uses the session token. albumRequest.requestHeaders.push(new URLRequestHeader('Authorization', authsubHeader)); // The X-HTTP-Method-Override header tells the Photos API to treat this request // as a GET request, even though it is being conducted as a POST (due to the bug // mentioned above). This is very important, as GData APIs will react differently // to different HTTP request types. albumRequest.requestHeaders.push(new URLRequestHeader('X-HTTP-Method-Override', 'GET')); // We expect ATOM XML to be returned. albumRequest.requestHeaders.push(new URLRequestHeader('Content-Type', 'application/atom+xml'));
Google 建議您提供手動登出功能,例如登出按鈕或可點擊的連結。這個方法可讓使用者在選擇時登出,或是保持登入狀態,方便他們下次存取應用程式時使用。
關於符記
本節說明 AuthSub 針對 ActionScript 使用的符記。大多數情況下,您不需要知道這項資訊。
每個驗證權杖都專屬於以下資料:
- Google 服務範圍
- 使用者的 Google 帳戶
- 用戶端應用程式
權杖資料可確保只有指定的第三方應用程式可以要求資料,而且該要求僅限於指定範圍和使用者帳戶中的資料。
這種範圍、使用者和用戶端的組合,隨時都只能有一個有效憑證。網路應用程式每次需要存取使用者的新 Google 服務時,都必須要求新的憑證。憑證涵蓋的存取權範圍取決於 Google 服務,且可能會選擇限制特定類型資料或活動的存取權,例如唯讀存取權。
使用 AuthSub for ActionScript 介面傳回的憑證可以視需要使用,直到撤銷憑證為止。管理憑證的生命週期是由應用程式主導,同時讓安全性變得更簡單。每當新的工作階段開始時,Google 建議您要求新的權杖。
部分 Google 服務可能只允許已註冊和使用安全權杖的網頁應用程式存取。這類服務不支援 ActionScript 的 AuthSub。如要使用安全憑證,貴機構必須向 Google 註冊 SSL 憑證,並簽署這些資料動態饋給的所有請求。