2008 年 10 月
簡介
觀眾
本文將逐步說明如何建立 Blogger 小工具。本文假設您已熟悉 Google Data API 和 JavaScript 用戶端程式庫。您也應精通 JavaScript,並有使用 gadgets.* 實作 OpenSocial 小工具的經驗。API。
這個範例也示範如何在小工具中順利使用外部程式庫。我使用 jQuery (主要是為了 UI 效果) 和 TinyMCE,這款所見即所得的富文字編輯器外掛程式非常實用。
動機
只要使用少量的 JavaScript,就能建立透過 Google Data API 搭配 JSON 的小工具。這類小工具的主要缺點是資料公開且為唯讀。如要建構更有趣的小工具,您需要存取使用者的私人資料 (這需要驗證)。到目前為止,還沒有充分運用 Google 帳戶 API 的好方法。AuthSub 需要瀏覽器重新導向,而 ClientLogin 會在用戶端公開使用者的憑證。就連破解type="url"
小工具也很不方便。
輸入 OAuth Proxy。
OAuth Proxy
如果您不熟悉 OAuth,這是一種驗證標準,可讓使用者與其他網站或小工具共用私人資料。OAuth 規格規定所有資料要求都必須經過數位簽署。這對安全性來說是好事,但如果是 JavaScript 小工具,管理私密金鑰和建立數位簽章並不安全。此外,跨網域問題也讓情況更加複雜。
幸好,只要善用小工具平台提供的 OAuth Proxy 功能,就能解決這些問題。OAuth Proxy 的設計宗旨是讓小工具開發人員的工作更輕鬆。這項功能會隱藏大部分的 OAuth 驗證詳細資料,並為您處理繁重的工作。Proxy 會代表小工具簽署資料要求,因此您不需要管理私密金鑰,也不必擔心要求簽署問題。輕輕鬆鬆就能上手!
OAuth Proxy 是以名為 Shindig 的開放原始碼專案為基礎,該專案實作了 Gadget 規格。
注意: OAuth Proxy 僅支援使用 gadgets.*
API 且在 OpenSocial 容器中執行的 Gadget。舊版小工具 API 不支援這項功能。
開始使用
本教學課程的其餘部分將著重於建立小工具,以存取使用者的 Blogger 資料。我們將逐步說明如何進行驗證 (使用 OAuth Proxy)、使用 JavaScript 用戶端程式庫,以及最後將項目發布至 Blogger。
驗證
首先,我們需要告知小工具使用 OAuth。如要這麼做,請在小工具的 <ModulePrefs>
區段中新增 <OAuth>
元素:
<ModulePrefs> ... <OAuth> <Service name="google"> <Access url="https://www.google.com/accounts/OAuthGetAccessToken" method="GET" /> <Request url="https://www.google.com/accounts/OAuthGetRequestToken?scope=http://www.blogger.com/feeds/" method="GET" /> <Authorization url="https://www.google.com/accounts/OAuthAuthorizeToken? oauth_callback=http://oauth.gmodules.com/gadgets/oauthcallback" /> </Service> </OAuth> ... </ModulePrefs>
<Service>
元素中的三個網址端點對應至 Google 的 OAuth 權杖端點。查詢參數說明如下:
scope
要求網址中必須有此參數。小工具只能存取這個參數中使用的
scope
(s) 資料。在本範例中,小工具將存取 Blogger。如果小工具要存取多個 Google Data API,請將額外的scope
(s) 與%20
串連。舉例來說,如要同時存取日曆和 Blogger,請將範圍設為http://www.blogger.com/feeds/%20http://www.google.com/calendar/feeds/
。oauth_callback
授權網址中可省略此參數。使用者核准存取資料後,OAuth 核准頁面會重新導向至這個網址。 您可以選擇省略這個參數、將參數設為自己的「核准的網頁」,或最好使用
http://oauth.gmodules.com/gadgets/oauthcallback
。後者可讓使用者在首次安裝小工具時獲得最佳體驗。該頁面提供 JavaScript 程式碼片段,可自動關閉彈出式視窗。
現在我們的小工具已使用 OAuth,使用者必須核准存取資料。驗證流程如下:
- 小工具首次載入,並嘗試存取使用者的 Blogger 資料。
- 要求失敗,因為使用者尚未授予小工具存取權。幸好,回應中傳回的物件包含一個網址 (
response.oauthApprovalUrl
),我們會將使用者導向該網址登入。小工具會顯示「登入 Blogger」,並將 href 設為oauthApprovalUrl
的值。 - 接著,使用者點按「登入 Blogger」,OAuth 核准頁面就會在另一個視窗中開啟。小工具會顯示「我已核准存取權」連結,等待使用者完成核准程序。
- 在彈出式視窗中,使用者會選擇授予/拒絕存取小工具的權限。點選「授予存取權」後,系統會將使用者導向
http://oauth.gmodules.com/gadgets/oauthcallback
,並關閉視窗。 - 小工具會辨識視窗是否已關閉,並重新要求使用者資料,嘗試第二次存取 Blogger。如要偵測視窗關閉,我使用了彈出式視窗處理常式。如果未使用這類代碼,使用者可以手動點選「我已核准存取權」。
- 小工具現在會顯示一般 UI。除非在「IssuedAuthSubTokens」IssuedAuthSubTokens中撤銷驗證權杖,否則這個檢視畫面會持續存在。
因此從上述步驟來看,小工具的概念有三種不同狀態:
- 未經驗證。使用者必須啟動核准程序。
- 等待使用者核准存取資料。
- 已通過驗證。小工具會顯示正常運作狀態。
在我的小工具中,我使用 <div>
容器分隔每個階段:
<Content type="html"> <![CDATA[ <!-- Normal state of the gadget. The user is authenticated --> <div id="main" style="display:none"> <form id="postForm" name="postForm" onsubmit="savePost(this); return false;"> <div id="messages" style="display: none"></div> <div class="selectFeed">Publish to: <select id="postFeedUri" name="postFeedUri" disabled="disabled"><option>loading blog list...</option></select> </div> <h4 style="clear:both">Title</h4> <input type="text" id="title" name="title"/> <h4>Content</h4> <textarea id="content" name="content" style="width:100%;height:200px;"></textarea> <h4 style="float:left;">Labels (comma separated)</h4><img src="blogger.png" style="float:right"/> <input type="text" id="categories" name="categories"/> <p><input type="submit" id="submitButton" value="Save"/> <input type="checkbox" id="draft" name="draft" checked="checked"/> <label for="draft">Draft?</label></p> </form> </div> <div id="approval" style="display: none"> <a href="#" id="personalize">Sign in to Blogger</a> </div> <div id="waiting" style="display: none"> <a href="#" id="approvalLink">I've approved access</a> </di <!-- An errors section is not necessary but great to have --> <div id="errors" style="display: none"></div> <!-- Also not necessary, but great for informing users --> <div id="loading"> <h3>Loading...</h3> <p><img src="ajax-loader.gif"></p> </div> ]]> </Content>
每個 <div>
都會使用 showOnly()
單獨顯示。如要瞭解該函式,請參閱完整範例小工具。
使用 JavaScript 用戶端程式庫
如要在 OpenSocial 中擷取遠端內容,請使用 gadgets.*
API 呼叫 gadgets.io.makeRequest
方法。不過,由於我們要建構 Google Data 小工具,因此不需要使用 gadgets.io.*
API。請改用 JavaScript 用戶端程式庫,其中有專用方法可向各項 Google Data 服務發出要求。
注意:撰寫本文時,JavaScript 程式庫僅支援 Blogger、Google 日曆、
Google 聯絡人、
Google 財經和 Google Base。如要使用其他 API,請在不使用程式庫的情況下使用 gadgets.io.makeRequest
。
載入程式庫
如要載入 JavaScript 程式庫,請在 <Content>
區段中加入一般載入器,並在小工具初始化後匯入程式庫。將回呼饋送至 gadgets.util.registerOnLoadHandler()
有助於判斷小工具何時準備就緒:
<Content type="html"> <![CDATA[ ... <script src="https://www.google.com/jsapi"></script> <script type="text/javascript"> var blogger = null; // make our service object global for later // Load the JS library and try to fetch data once it's ready function initGadget() { google.load('gdata', '1.x', {packages: ['blogger']}); // Save overhead, only load the Blogger service google.setOnLoadCallback(function () { blogger = new google.gdata.blogger.BloggerService('google-BloggerGadget-v1.0'); blogger.useOAuth('google'); fetchData(); }); } gadgets.util.registerOnLoadHandler(initGadget); </script> ... ]]> </Content>
呼叫 blogger.useOAuth('google')
會告知程式庫使用 OAuth Proxy (而非 AuthSubJS,也就是程式庫的一般驗證方法)。最後,小工具會呼叫 fetchData()
,嘗試擷取使用者的 Blogger 資料。該方法定義如下。
正在擷取資料
現在一切都已設定完成,我們該如何將 GET
或 POST
資料實際傳送至 Blogger?
OpenSocial 的常見範例是在小工具中定義名為 fetchData()
的函式。這個方法通常會處理驗證的不同階段,並使用 gadgets.io.makeRequest
擷取資料。由於我們使用的是 JavaScript 用戶端程式庫,gadgets.io.makeRequest
會替換為對 blogger.getBlogFeed()
的呼叫:
function fetchData() { jQuery('#errors').hide(); var callback = function(response) { if (response.oauthApprovalUrl) { // You can set the sign in link directly: // jQuery('#personalize').get(0).href = response.oauthApprovalUrl // OR use the popup.js handler var popup = shindig.oauth.popup({ destination: response.oauthApprovalUrl, windowOptions: 'height=600,width=800', onOpen: function() { showOnly('waiting'); }, onClose: function() { showOnly('loading'); fetchData(); } }); jQuery('#personalize').get(0).onclick = popup.createOpenerOnClick(); jQuery('#approvalLink').get(0).onclick = popup.createApprovedOnClick(); showOnly('approval'); } else if (response.feed) { showResults(response); showOnly('main'); } else { jQuery('#errors').html('Something went wrong').fadeIn(); showOnly('errors'); } }; blogger.getBlogFeed('http://www.blogger.com/feeds/default/blogs', callback, callback); }
第二次呼叫這個函式時,response.feed
包含資料。
注意:getBlogFeed()
的回呼和錯誤處理常式使用相同函式。
在 Blogger 上發布文章
最後一步是在網誌中發布新文章。下方程式碼說明使用者點選「儲存」按鈕時會發生什麼情況。
function savePost(form) { jQuery('#messages').fadeOut(); jQuery('#submitButton').val('Publishing...').attr('disabled', 'disabled'); // trim whitespace from the input tags var input = form.categories.value; var categories = jQuery.trim(input) != '' ? input.split(',') : []; jQuery.each(categories, function(i, value) { var label = jQuery.trim(value); categories[i] = { scheme: 'http://www.blogger.com/atom/ns#', term: label }; }); // construct the blog post entry var newEntry = new google.gdata.blogger.BlogPostEntry({ title: { type: 'text', text: form.title.value }, content: { type: 'text', text: form.content.value }, categories: categories }); // publish as draft? var isDraft = form.draft.checked; if (isDraft) { newEntry.setControl({draft: {value: google.gdata.Draft.VALUE_YES}}); } // callback for insertEntry() var handleInsert = function(entryRoot) { var entry = entryRoot.entry; var str = isDraft ? '(as draft)' : '<a href="' + entry.getHtmlLink().getHref() + '" target="_blankt">View it</a>'; jQuery('#messages').html('Post published! ' + str).fadeIn(); jQuery('#submitButton').val('Save').removeAttr('disabled'); }; // error handler for insertEntry() var handleError = function(e) { var msg = e.cause ? e.cause.statusText + ': ' : ''; msg += e.message; alert('Error: ' + msg); }; blogger.insertEntry(form.postFeedUri.value, newEntry, handleInsert, handleError); }
結論
現在您已具備基本知識,可以開始使用 Google Data API 編寫小工具。
希望本文能讓您瞭解 OAuth Proxy 如何簡化小工具驗證程序。結合這項強大工具與 Google Data JavaScript 用戶端程式庫,即可輕鬆建構有趣、互動式且精緻的小工具。
如對本文有任何疑問或意見,請前往 Google 帳戶 API 討論論壇。
資源
- 撰寫 OAuth 小工具 (完整的小工具說明文件)
- 搭配 Google Data API 使用 OAuth (說明如何搭配 Google Data API 使用 OAuth 的文章)
- 網頁應用程式的 OAuth 驗證 (完整 OAuth 說明文件)
- JavaScript 用戶端程式庫
- Google Accounts API 討論區