本文說明如何從 Flash 或 Silverlight 應用程式使用 Google 的 AuthSub 驗證系統。
注意:如果您已熟悉 AuthSub (Google 的網頁應用程式帳戶驗證服務),就會發現 ActionScript 的 AuthSub 在概念上非常相似。底層實作方式不同,但對用戶端應用程式開發人員而言,這些差異並不重要。在某些說明文件中,如果區別不重要,我們會簡稱 ActionScript 的 AuthSub 為「AuthSub」。
Flash 或 Silverlight 應用程式可透過 ActionScript 介面的 AuthSub,代表使用者向受保護的 Google Data API 資訊動態饋給進行驗證。為維持高安全等級,應用程式可透過這個介面取得驗證權杖,完全不必處理使用者的帳戶登入資訊。
ActionScript 適用的 AuthSub 是 JavaScript 適用的 AuthSub 變體。與 JavaScript 適用的 AuthSub 類似,這個方法也提供跨網域驗證機制,讓用戶端應用程式從非 Google 網域代管的網頁進行驗證。與標準 AuthSub 不同的是,驗證服務位於不同網域 (accounts.googleapis.com,而非 www.google.com),並提供 crossdomain.xml 檔案,允許從外部網站存取該網域。
如要討論如何使用所有 Authentication 服務 API,請參閱 Google 帳戶 API 群組。
觀眾
本文適用於開發會存取 Google 服務的 Flash 或 Silverlight 網頁應用程式的程式設計師。
本文假設您瞭解 Google Data APIs 通訊協定和 AuthSub 介面背後的概念。同時假設您知道如何使用 ActionScript 編寫程式。
支援的環境
目前 Firefox 1.5 以上版本和 Internet Explorer 6.0 以上版本支援 ActionScript 的 AuthSub,但須搭配 Flash 9.0 以上版本或 Silverlight 2.0 以上版本。
ActionScript 的 AuthSub 運作方式
以下簡要說明網路應用程式、Google 驗證服務和 Google 資料服務之間的通訊方式:
- 如要代表使用者存取 Google 資料服務,網路應用程式必須具備有效的驗證權杖。應用程式通常會將這個權杖儲存在 Cookie 中;如果沒有這類 Cookie,網路應用程式就必須透過 AuthSub 取得權杖。如要取得權杖,網頁應用程式會向 Authentication 服務發出 AuthSub for ActionScript 登入呼叫,並指定要存取的服務。
- 驗證服務收到網頁應用程式的要求後,會將使用者重新導向至「存取要求」頁面。這個頁面會提示使用者登入 Google 帳戶,並要求他們授予或拒絕存取 Google 服務的權限。
- 使用者可決定是否要授予網頁應用程式存取權。如果使用者拒絕存取權,系統會將他們導向 Google 網頁,而非返回網頁應用程式。
- 如果使用者成功登入並授予存取權,驗證服務會將使用者重新導向至發出原始呼叫的網頁應用程式網址。重新導向會透過查詢參數,為指定服務提供驗證權杖。應用程式應將權杖儲存為使用者瀏覽器中網頁應用程式網域下的 Cookie。憑證在撤銷前有效。(如需撤銷權杖時機的建議,請參閱「關於權杖」一節)。
- 網路應用程式會與 Google Data 服務聯絡,並在傳送給服務的每個要求中附上驗證權杖。
- 如果 Google Data 服務可辨識權杖,就會提供要求的資料。
使用 ActionScript 介面的 AuthSub
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,必須針對要存取的每個外部網域,使用政策進行初始化。如要這麼做,請為每個網域叫用 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(Picasa 網路相簿,範例稍後會存取) 的政策。 - 要求一次性權杖。
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 for ActionScript 使用的權杖。在大多數情況下,您不需要知道這項資訊。
每個驗證權杖都專屬於下列資料:
- Google 服務範圍
- 使用者的 Google 帳戶
- 用戶端應用程式
權杖資料可確保只有指定的第三方應用程式可以要求資料,且要求僅限於指定範圍和使用者帳戶的資料。
在任何時間,這個範圍、使用者和用戶端組合只能有一個有效權杖。網頁應用程式每次需要存取特定使用者的 Google 服務時,都必須要求新的權杖。權杖涵蓋的存取範圍取決於 Google 服務,服務可能會選擇限制特定類型資料或活動的存取權,例如唯讀存取權。
ActionScript 介面的 AuthSub 傳回的權杖可重複使用,直到遭到撤銷為止。應用程式必須自行管理權杖的生命週期,同時兼顧安全性和便利性。Google 建議每次啟動新工作階段時,都要求新的符記。
部分 Google 服務可能只允許已註冊且使用安全權杖的網路應用程式存取。這類服務不支援 ActionScript 的 AuthSub。如要使用安全權杖,貴機構必須向 Google 註冊 SSL 憑證,並簽署所有資料動態饋給的要求。