2007 年 8 月
簡介:AuthSub 的重要性
Google Data API (簡稱「GData」) 的優點在於,開發人員可藉此建構與 Google 服務互動的應用程式。具體來說,這些權限可讓您存取使用者私人資料,並用於應用程式中。您可以使用這些 API 編寫應用程式,同步處理、匯入、匯出及管理資料。雖然這些 API 賦予您強大的能力,但請務必負責任地使用。使用者資料屬於私人資訊,因此您自然會希望以安全的方式存取。其中一個重要環節,就是以安全的方式向 Google 伺服器進行驗證。
假設您有一個很棒的新網路應用程式,想要與 Google 網路服務中儲存的資料連結。現在您想要進行驗證,以便存取這項私人資料。為什麼不使用 ClientLogin 等簡單的驗證方式?這樣做確實可以解決問題,但您要處理的私人資料更多了:使用者的登入憑證。ClientLogin 會要求應用程式索取使用者的 Google 使用者名稱和密碼。這對在使用者個人電腦上執行的桌面應用程式來說沒問題,但對網頁應用程式來說就不是那麼理想。除了自行在伺服器上處理這些憑證的責任外,或許有些比較謹慎的使用者會擔心您可能會儲存他們的資訊。使用者另一個常見的疑慮是,他們只希望授權程式存取特定服務 (例如 Google 日曆中的活動),但不想授權存取其他服務 (例如 Google 文件)。AuthSub 可讓使用者透過 Google 伺服器進行驗證,並只允許程式要求所需的存取權,因此能解決上述兩個問題。
您已充分瞭解 AuthSub 背後的理論,現在可以開始編寫程式碼了!在本文中,我選擇簡化一切,在單一 ASP 網頁中完成所有作業,但您應該可以輕鬆將本文示範的技術整合到自己的應用程式中。
處理驗證
那麼,在網頁應用程式中實際使用 AuthSub 時,需要哪些項目?首先,請從 GData 用戶端程式庫匯入一些標準項目:
<%@ Import Namespace="Google.GData.Client" %> <%@ Import Namespace="Google.GData.Extensions" %> <%@ Import Namespace="System.Net" %>
現在,您必須先將使用者帶往特別製作的網址。Google 伺服器就是透過這項設定處理驗證,然後將使用者重新導向至您的網站。幸好您不必手動產生這個網址,因為有方法可以為您產生。讓我們看看以下範例:
authSubUrl = AuthSubUtil.getRequestUrl(target, scope, secure, session);
- target:這是包含網頁應用程式網址的字串。使用者完成驗證後,系統會將他們重新導向至這個網址。
- 範圍:這個字串取決於您使用的 API。這對應於 GData API 中的其中一個動態饋給。舉例來說,包含使用者所有日曆資訊的動態消息是「http://www.google.com/calendar/feeds/default/private/full」。
- secure:這是布林值,會告知伺服器您已向 Google 註冊,並將以加密方式簽署對伺服器的要求。這個引數預設通常為 false,尤其是在測試環境中作業時。
- session:這是另一個布林值,表示您想要「工作階段權杖」,而非「一次性權杖」。稍後您會更清楚瞭解這個引數的角色。
使用者點選產生的網址後,系統會將他們帶往 Google 帳戶頁面,讓他們登入 Google 帳戶。接著,系統會將他們重新導向至您在「target」變數中指定的網頁,但會附上含有一次性權杖的「token」查詢參數。通常這個權杖只能使用一次。也就是說,這項功能可用於對特定動態饋給執行一項動作。不過,如果您將「session」參數指定為 true,則可換取「工作階段權杖」,在使用者結束工作階段前重複使用。方法如下:
String token = Request.QueryString["token"]; Session["token"] = AuthSubUtil.exchangeForSessionToken(token, null).ToString();
您可以在這裡從查詢參數擷取權杖,並換取「工作階段權杖」。然後,為了儲存以供日後使用,您可以選擇將權杖儲存在 .NET 的自動 Session
陣列中。當然,您也可以選擇將權杖儲存在資料庫中。下一步是使用這個權杖發出已驗證的要求:
GAuthSubRequestFactory authFactory = new GAuthSubRequestFactory("cl", "My-Cool-Application"); authFactory.Token = (String) Session["token"]; CalendarService service = new CalendarService(authFactory.ApplicationName); service.RequestFactory = authFactory;
您可以在這裡設定 CalendarService 物件,透過 AuthSub 進行驗證,與 Google Calendar API 互動。請注意,建構函式中使用的「cl」是日曆的服務名稱。GAuthSubRequestFactory
如需其他服務名稱,請參閱 Google Data API 常見問題。
安全 (已註冊) AuthSub
如果您選擇註冊網路應用程式,使用 AuthSub 時就能啟用額外的安全防護。這樣一來,您就能以數位方式簽署程式碼提出的所有要求,確保只有擁有私密金鑰的使用者,才能使用發給您的 AuthSub 權杖。第一步是呼叫 AuthSubUtil.getRequestUrl
時,請將「secure」引數設為 true,確保產生正確的 AuthSub 連結。您還需要進行兩項程式碼變更:
String token = Request.QueryString["token"]; Session["token"] = AuthSubUtil.exchangeForSessionToken(token, rsaKey).ToString(); ... authFactory.PrivateKey = rsaKey;
首先,請注意您現在會將「rsaKey」變數傳遞至 exchangeForSessionToken
方法,而不是 null
。設定服務連線時,也會使用這個變數設定 GAuthSubRequestFactory
的屬性。「rsaKey」變數是 RSACryptoServiceProvider
,對應於您向 Google 註冊的 x509 憑證私密金鑰元件。
產生 RSA 私密金鑰和自行簽署的憑證可能有點令人困惑,尤其是 .NET 架構無法解讀以 PEM 格式儲存的金鑰或憑證。下列指令說明如何使用 OpenSSL 工具套件產生私密金鑰和公開憑證:
openssl req -x509 -nodes -days 365 -newkey rsa:1024 -sha1 -subj \ '/C=US/ST=CA/L=Mountain View/CN=www.example.com' -keyout \ test_key.pem -out test_cert.pem openssl pkcs12 -export -in test_cert.pem -inkey test_key.pem \ -out test_cert.pfx -name "Testing Certificate"
第一個步驟會產生 PEM 格式的私密金鑰和公開 X509 憑證,分別命名為「test_key.pem」和「test_cert.pem」。請注意,憑證已設為向美國加州山景城的「www.example.com」註冊。請在此處代入貴公司的適當值。「test_cert.pem」檔案包含您需要在 AuthSub 註冊頁面提交的資訊。
第二個步驟會從私密金鑰和憑證產生 PFX 檔案。這個檔案可以匯入 .NET 用戶端程式庫,用來以數位方式簽署向 GData API 發出的要求。下列程式碼說明如何將 PFX 檔案中的私鑰匯入網路應用程式:
protected AsymmetricAlgorithm getRsaKey() { X509Certificate2 cert = new X509Certificate2("C:/MyAspSite/test_cert.pfx",""); RSACryptoServiceProvider privateKey = cert.PrivateKey as RSACryptoServiceProvider; return privateKey; }
使用 API 進行驗證時,可以將這個程式碼片段定義的 getRsaKey()
函式,替換成上述「rsaKey」變數。當然,檔案路徑應替換為您產生的 PFX 檔案所在位置。
完整程式碼清單
如要輕鬆展示如何使用上一節中示範的方法,最簡單的方式就是提供實際範例。下列程式碼範例是簡單的 ASP 網頁,會使用 AuthSub 驗證使用者,然後列印出他們的 Google 日曆活動。
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <%@ Import Namespace="Google.GData.Client" %> <%@ Import Namespace="Google.GData.Extensions" %> <%@ Import Namespace="Google.GData.Calendar" %> <%@ Import Namespace="System.Net" %> <script runat="server"> void PrintCalendar() { GAuthSubRequestFactory authFactory = new GAuthSubRequestFactory("cl", "TesterApp"); authFactory.Token = (String) Session["token"]; CalendarService service = new CalendarService(authFactory.ApplicationName); service.RequestFactory = authFactory; EventQuery query = new EventQuery(); query.Uri = new Uri("http://www.google.com/calendar/feeds/default/private/full"); try { EventFeed calFeed = service.Query(query); foreach (Google.GData.Calendar.EventEntry entry in calFeed.Entries) { Response.Write("Event: " + entry.Title.Text + "<br/>"); } } catch (GDataRequestException gdre) { HttpWebResponse response = (HttpWebResponse)gdre.Response; //bad auth token, clear session and refresh the page if (response.StatusCode == HttpStatusCode.Unauthorized) { Session.Clear(); Response.Redirect(Request.Url.AbsolutePath, true); } else { Response.Write("Error processing request: " + gdre.ToString()); } } } </script> <html xmlns="http://www.w3.org/1999/xhtml" > <head runat="server"> <title>Test Site</title> </head> <body> <form id="form1" runat="server"> <h1>AuthSub Sample Page</h1> <div> <% GotoAuthSubLink.Visible = false; if (Session["token"] != null) { PrintCalendar(); } else if (Request.QueryString["token"] != null) { String token = Request.QueryString["token"]; Session["token"] = AuthSubUtil.exchangeForSessionToken(token, null).ToString(); Response.Redirect(Request.Url.AbsolutePath, true); } else //no auth data, print link { GotoAuthSubLink.Text = "Login to your Google Account"; GotoAuthSubLink.Visible = true; GotoAuthSubLink.NavigateUrl = AuthSubUtil.getRequestUrl(Request.Url.ToString(), "http://www.google.com/calendar/feeds/",false,true); } %> <asp:HyperLink ID="GotoAuthSubLink" runat="server"/> </div> </form> </body> </html>
結論
AuthSub 可讓網路應用程式以安全且受控的方式,存取使用者 Google 帳戶中儲存的資料。使用 .NET 用戶端程式庫,即可輕鬆將 ASP 架構的網站與 Google 服務整合。本文旨在協助您入門,但我們建議您參考其他資源: