警告:本頁面介紹的是 Google 舊版 API (Google Data API),僅適用於Google Data API 目錄中列出的 API,其中許多 API 已由新版 API 取代。如要瞭解特定新版 API,請參閱該 API 的說明文件。如要瞭解如何使用較新的 API 授權要求,請參閱「Google 帳戶驗證和授權」。
本文說明如何使用 Google Data API 用戶端程式庫,連線至 Google 的網路應用程式 AuthSub 驗證。
網頁應用程式可透過 AuthSub 介面,代表使用者存取 Google 服務。為維持高安全性,應用程式可透過 AuthSub 介面取得驗證權杖,完全不必處理使用者的帳戶登入資訊。
Google Data API 用戶端程式庫提供的方法可協助您在網頁應用程式中使用 AuthSub。具體來說,這些方法包括建構要求網址、取得一次性驗證權杖、將一次性權杖換成工作階段權杖,以及簽署要求。
注意:JavaScript 用戶端程式庫有自己的 AuthSub 版本,稱為 AuthSubJS。如要瞭解如何在 JavaScript 應用程式中使用 AuthSubJS,請參閱「使用 JavaScript 用戶端程式庫進行『AuthSub』驗證」。
觀眾
本文適用於想讓網路應用程式代表使用者存取 Google 服務的程式設計人員,並使用 Google Data API 用戶端程式庫。
本文假設您已熟悉 AuthSub 介面,以及將 AuthSub 併入網路應用程式的一般程序。如需 AuthSub 通訊協定的完整說明,請參閱「網頁應用程式的 AuthSub 驗證」。
不使用用戶端程式庫,透過 AuthSub 和 Google Data API 進行驗證
如果想讓網路應用程式用戶端使用 AuthSub 做為驗證系統,與 Google 資料服務互動, 那麼您真正需要瞭解的內容都在「網路應用程式適用的 AuthSub 驗證」一文中。 如果您不想使用,則不必使用 Google Data API 用戶端程式庫。
以下是應用程式如何使用 AuthSub 驗證使用者的流程大綱:
應用程式會建構適當的 AuthSub 網址,然後將使用者傳送至該網址,讓他們登入;AuthSub 系統會將使用者傳送回您指定的網站網址,並傳回一次性權杖;應用程式可選擇將該權杖換成工作階段權杖;然後應用程式會在傳送至服務的每個要求中,將權杖傳送至授權標頭。
Google Data API 用戶端程式庫會為您處理各種詳細資料,簡化授權程序。本文將說明如何操作。
使用 AuthSub 和 Google Data API:用戶端程式庫範例
本節提供範例,說明如何使用 Google Data API 用戶端程式庫方法,按照 AuthSub 說明文件「使用 AuthSub」一節所述步驟操作。
在本範例中,我們將 AuthSub 介面整合至與 Google 日曆互動的網路應用程式 (但您不需要瞭解 Google 日曆,即可按照範例操作)。這個範例假設網頁應用程式託管於 example.com。
決定要使用的權杖類型 (session=0 或 session=1)
您可以選擇使用單次使用權杖 (session=0) 或工作階段權杖 (session=1)。
本文將使用工作階段權杖,因為這類權杖在會發出多個 API 要求的應用程式中較為實用。
如 AuthSub 說明文件所述,如果您決定在網路應用程式中使用工作階段符記,就必須自行管理符記儲存空間。本文未涵蓋權杖管理。另請注意,以 session=0 要求取得的權杖之後無法兌換 (升級) 為長期工作階段權杖。
決定是否要註冊網頁應用程式 (secure=0 或 secure=1)
AuthSub 可用於三種不同模式:未註冊、已註冊和已註冊並啟用強化安全性。本文的其餘部分會將最後一個選項稱為安全 AuthSub。雖然未註冊/已註冊模式比安全的 AuthSub 更容易設定,但 Google 建議您使用安全權杖,以提升安全性。
登記方式
選擇「Registration for Web-Based Applications」(註冊網頁應用程式),可為應用程式帶來下列好處:
- 安全性更高。
- 獲得 Google 信任 (Google 授權頁面不會向使用者顯示警告)。
已註冊 + 安全的 AuthSub
如果您決定採用安全的 AuthSub,除了註冊網路應用程式外,還需要建立自行簽署的 RSA 私密金鑰和公開憑證組。 如需建立 X.509 憑證的範例,請參閱下方的「產生金鑰和憑證,以搭配已註冊模式使用」。
判斷資料存取範圍
每項 Google 服務都會定義 scope 值,決定 (並可能縮減) 權杖對使用者資料的存取權。如需可用的 scope 值清單,請參閱常見問題。
由於我們決定與 Google Calendar API 互動,因此 scope 應為 http://www.google.com/calendar/feeds/。
注意:除非需要更精細的限制,否則請一律將範圍值設為最廣泛的網址。
舉例來說,較窄的範圍 (如 scope=http://www.google.com/calendar/feeds/default/allcalendars/full) 會將權杖的存取權限制為僅限 allcalendars/full 資訊動態消息。使用 scope=http://www.google.com/calendar/feeds/ 可存取所有日曆動態消息:http://www.google.com/calendar/feeds/*。
多範圍權杖
如要建立可存取多個 Google Data API 的權杖,請以網址編碼的空格分隔每個範圍。以下範例會建立權杖,可存取使用者的 Google 聯絡人和 Google 日曆資料。
scope=http://www.google.com/calendar/feeds/%20http://www.google.com/m8/feeds/
要求一次性驗證權杖
如要取得特定使用者和特定服務的 AuthSub 權杖,應用程式必須將使用者重新導向 AuthSubRequest URL,提示他們登入 Google 帳戶。
(如要進一步瞭解 AuthSubRequest URL,請參閱完整的「網路應用程式的 AuthSub 驗證」一文)。
如要在應用程式中建構 AuthSubRequest 網址,請為每個用戶端程式庫使用下列項目:
Java
import com.google.gdata.client.*; String nextUrl = "http://www.example.com/RetrieveToken.jsp"; String scope = "http://www.google.com/calendar/feeds/"; boolean secure = false; // set secure=true to request secure AuthSub tokens boolean session = true; String authSubUrl = AuthSubUtil.getRequestUrl(nextUrl, scope, secure, session);
如要驗證 G Suite 網域的使用者:
import com.google.gdata.client.*; String hostedDomain = "example.com"; String nextUrl = "http://www.example.com/RetrieveToken.jsp"; String scope = "http://www.google.com/calendar/feeds/"; boolean secure = false; // set secure=true to request AuthSub tokens boolean session = true; String authSubUrl = AuthSubUtil.getRequestUrl(hostedDomain, nextUrl, scope, secure, session);
.NET
using Google.GData.Client; String nextUrl = "http://www.example.com/RetrieveToken.aspx"; String scope = "http://www.google.com/calendar/feeds/"; bool secure = false; // set secure=true to request secure AuthSub tokens bool session = true; String authSubUrl = AuthSubUtil.getRequestUrl(nextUrl, scope, secure, session);
如要驗證 G Suite 網域的使用者:
using Google.GData.Client; String hostedDomain = "example.com"; String nextUrl = "http://www.example.com/RetrieveToken.aspx"; String scope = "http://www.google.com/calendar/feeds/"; bool secure = false; // set secure=true to request secure AuthSub tokens bool session = true; String authSubUrl = AuthSubUtil.getRequestUrl(hostedDomain, nextUrl, scope, secure, session);
PHP
require_once 'Zend/Loader.php'; Zend_Loader::loadClass('Zend_Gdata_AuthSub'); $nextUrl = 'http://www.example.com/RetrieveToken.php'; $scope = 'http://www.google.com/calendar/feeds/'; $secure = 0; // set $secure=1 to request secure AuthSub tokens $session = 1; $authSubUrl = Zend_Gdata_AuthSub::getAuthSubTokenUri($nextUrl, $scope, $secure, $session);
如要驗證 G Suite 網域的使用者:
require_once 'Zend/Loader.php'; Zend_Loader::loadClass('Zend_Gdata_AuthSub'); $hostedDomain = 'example.com'; $nextUrl = 'http://www.example.com/RetrieveToken.php'; $scope = 'http://www.google.com/calendar/feeds/'; $secure = 0; // set $secure=1 to request secure AuthSub tokens $session = 1; $authSubUrl = Zend_Gdata_AuthSub::getAuthSubTokenUri($nextUrl, $scope, $secure, $session) . '&hd=' . $hostedDomain;
Python
import gdata.auth next = 'http://www.example.com/RetrieveToken.pyc' scope = 'http://www.google.com/calendar/feeds/' secure = False # set secure=True to request secure AuthSub tokens session = True auth_sub_url = gdata.auth.GenerateAuthSubRequestUrl(next, scope, secure=secure, session=session)
如要驗證 G Suite 網域的使用者:
import gdata.auth hosted_domain = 'example.com' next = 'http://www.example.com/RetrieveToken.pyc' scope = 'http://www.google.com/calendar/feeds/' secure = False # set secure=True to request secure AuthSub tokens session = True auth_sub_url = gdata.auth.GenerateAuthSubRequestUrl(next, scope, secure=secure, session=session, domain=hosted_domain)
建構「next」網址後,應用程式可透過多種方式使用該網址,將使用者傳送至 AuthSubRequest 處理常式。最常見的做法是顯示網頁,告知使用者必須點選連結,授權應用程式存取 Google 帳戶,然後將要求網址附加至連結。舉例來說,您可以在網頁應用程式中輸出下列字串:
String authorizationUrl =
"<p>MyApp needs access to your Google Calendar account to read your Calendar feed. " +
"To authorize MyApp to access your account, <a href=\"" + authSubUrl + "\">log in to your account</a>.</p>";使用者點選連結前往 Google 的 AuthSub 頁面,然後登入。AuthSub 系統會使用您提供的「next」網址,將使用者重新導向回應用程式。
擷取單次使用的權杖
Google 重新導向回應用程式時,權杖會以查詢參數的形式附加至「next」網址。以上述範例為例,使用者登入後,Google 會重新導向至類似 http://www.example.com/RetrieveToken?token=DQAADKEDE 的網址。應用程式應從網址查詢參數中擷取權杖值。
如果應用程式在將使用者傳送至 AuthSub 系統之前,已在使用者瀏覽器中設定驗證 Cookie,那麼當 Google 重新導向至「next」網址時,應用程式就能讀取驗證 Cookie,辨識出抵達該網址的使用者。您可以使用這類 Cookie,將應用程式中的使用者 ID 與從 Google 擷取的 AuthSub 權杖建立關聯。
用戶端程式庫提供便利的方法來擷取一次性權杖:
Java
String singleUseToken = AuthSubUtil.getTokenFromReply(httpServletRequest.getQueryString());
.NET
String singleUseToken = Request.QueryString["token"]; // or String singleUseToken = AuthSubUtil.getTokenFromReply(new Uri(Request.QueryString));
PHP
$singleUseToken = $_GET['token'];Python
current_url = 'http://' + req.hostname + req.unparsed_uri # Unlike the other calls, extract_auth_sub_token_from_url() will create anAuthSubTokenorSecureAuthSubTokenobject. # Use str(single_use_token) to return the token's string value. single_use_token = gdata.auth.extract_auth_sub_token_from_url(current_url)
如果您使用安全的 AuthSub,請務必設定 RSA 私密金鑰,以便建立 SecureAuthSubToken:
f = open('/path/to/yourRSAPrivateKey.pem') rsa_key = f.read() f.close() current_url = 'http://' + req.hostname + req.unparsed_uri # Unlike the other calls, extract_auth_sub_token_from_url() will create anAuthSubTokenorSecureAuthSubTokenobject. # Use str(single_use_token) to return the token's string value. single_use_token = gdata.auth.extract_auth_sub_token_from_url(current_url, rsa_key=rsa_key)
要求工作階段權杖
從網址擷取的權杖一律為單次使用權杖。下一步是使用 AuthSubSessionToken 網址升級該權杖,取得長期有效的會期權杖,詳情請參閱完整的「網路應用程式的 AuthSub 驗證」文件。如果您使用安全 AuthSub,必須先設定 RSA 私密金鑰,才能進行交換。以下是使用各個用戶端程式庫的範例:
Java
import com.google.gdata.client.*; import com.google.gdata.client.calendar.*; String sessionToken = AuthSubUtil.exchangeForSessionToken(singleUseToken, null); CalendarService calendarService = new CalendarService("google-ExampleApp-v1.0"); calendarService.setAuthSubToken(sessionToken, null); // ready to interact with Calendar feeds
如要使用安全的 AuthSub,請將 RSA 私密金鑰傳遞至 exchangeForSessionToken,而非 null:
import com.google.gdata.client.*; import com.google.gdata.client.calendar.*; java.security.PrivateKey privateKey = AuthSubUtil.getPrivateKeyFromKeystore("AuthSubExample.jks", "privKeyPa$$word", "AuthSubExample", "privKeyPa$$word"); String sessionToken = AuthSubUtil.exchangeForSessionToken(singleUseToken, privateKey); CalendarService calendarService = new CalendarService("google-ExampleApp-v1.0"); calendarService.setAuthSubToken(sessionToken, privateKey); // ready to interact with Calendar feeds
.NET
using Google.GData.Client; using Google.GData.Calendar; String sessionToken = AuthSubUtil.exchangeForSessionToken(singleUseToken, null).ToString(); GAuthSubRequestFactory authFactory = new GAuthSubRequestFactory("cl", "google-ExampleApp-v1.0"); authFactory.Token = (String) sessionToken; CalendarService calendarService = new CalendarService(authFactory.ApplicationName); calendarService.RequestFactory = authFactory; // ready to interact with Calendar feeds
如要使用安全的 AuthSub,請將 RSA 私密金鑰傳遞至 exchangeForSessionToken,而非 null:
using Google.GData.Client; using Google.GData.Calendar; protected AsymmetricAlgorithm getRsaKey() { X509Certificate2 cert = new X509Certificate2("C:/MyAspSite/test_cert.pfx", "privKeyPa$$word"); RSACryptoServiceProvider privateKey = cert.PrivateKey as RSACryptoServiceProvider; return privateKey; } AsymmetricAlgorithm rsaKey = getRsaKey(); String sessionToken = AuthSubUtil.exchangeForSessionToken(singleUseToken, rsaKey).ToString(); GAuthSubRequestFactory authFactory = new GAuthSubRequestFactory("cl", "google-ExampleApp-v1.0"); authFactory.Token = (String) sessionToken; authFactory.PrivateKey = rsaKey; CalendarService calendarService = new CalendarService(authFactory.ApplicationName); calendarService.RequestFactory = authFactory; // ready to interact with Calendar feeds
PHP
require_once 'Zend/Loader.php'; Zend_Loader::loadClass('Zend_Gdata_AuthSub'); Zend_Loader::loadClass('Zend_Gdata_Calendar'); $sessionToken = Zend_Gdata_AuthSub::getAuthSubSessionToken($singleUseToken); // Create a Calendar service object and set the session token for subsequent requests $calendarService = new Zend_Gdata_Calendar(null, 'google-ExampleApp-v1.0'); $calendarService->setAuthSubToken($sessionToken); // ready to interact with Calendar feeds
如要使用安全 AuthSub,您必須先設定 Zend_Gdata_HttpClient,並使用 setAuthSubPrivateKeyFile() 設定 RSA 私密金鑰,才能進行交換:
require_once 'Zend/Loader.php'; Zend_Loader::loadClass('Zend_Gdata_AuthSub'); Zend_Loader::loadClass('Zend_Gdata_Calendar'); $client = new Zend_Gdata_HttpClient(); $client->setAuthSubPrivateKeyFile('/path/to/myrsakey.pem', null, true); $sessionToken = Zend_Gdata_AuthSub::getAuthSubSessionToken($singleUseToken, $client); $calendarService = new Zend_Gdata_Calendar($client, 'google-ExampleApp-v1.0'); $calendarService->setAuthSubToken($sessionToken); // ready to interact with Calendar feeds
Python
import gdata.calendar import gdata.calendar.service calendar_service = gdata.calendar.service.CalendarService() calendar_service.UpgradeToSessionToken(single_use_token) # calls gdata.service.SetAuthSubToken() for you # ready to interact with Calendar feeds
注意:只要您使用 gdata.auth.extract_auth_sub_token_from_url(url, rsa_key=rsa_key) 擷取單次使用權杖,安全 AuthSub 的程序就相同。
注意:使用安全 AuthSub 時,系統不會透過網路傳送私密金鑰。用戶端程式庫會傳送透過金鑰簽署要求產生的專屬簽章,而非金鑰本身。
使用工作階段權杖
您可以將權杖放在 Authorization 標頭中,藉此驗證對伺服器的要求,詳情請參閱 AuthSub 說明文件。
設定工作階段權杖後,您可以使用標準的 Google Data API 用戶端程式庫呼叫與服務互動,不必考慮權杖。詳情請參閱您互動的服務和語言的用戶端程式庫說明文件,以及 Google Data API 開發人員指南。
擷取工作階段權杖的相關資訊
如要測試用戶端和伺服器是否同意權杖的參數,可以將權杖傳遞至 AuthSubTokenInfo 處理常式,該常式會傳回一組包含權杖相關資訊的名稱/值配對。
Java
Map<String, String> tokenInfo = AuthSubUtil.getTokenInfo(sessionToken, null);
如果您使用安全的 AuthSub,請傳遞 RSA 私密金鑰:
Map<String, String> tokenInfo = AuthSubUtil.getTokenInfo(sessionToken, privateKey);
.NET
Dictionary<String, String> tokenInfo = AuthSubUtil.GetTokenInfo(sessionToken, null);
如果您使用安全的 AuthSub,請傳遞 RSA 私密金鑰:
Dictionary<String, String> tokenInfo = AuthSubUtil.GetTokenInfo(sessionToken, privateKey);
PHP
$tokenInfo = Zend_Gdata_AuthSub::getAuthSubTokenInfo($sessionToken);如果您使用安全的 AuthSub,請傳遞 Zend_Gdata_HttpClient,以便使用 RSA 私密金鑰簽署要求:
$tokenInfo = Zend_Gdata_AuthSub::getAuthSubTokenInfo($sessionToken, $client);Python
token_info = calendar_service.AuthSubTokenInfo()
撤銷工作階段權杖
AuthSub 工作階段符記不會過期,用戶端可視需要儲存工作階段符記。
因此,用戶端使用完工作階段權杖後,可以按照 AuthSub 說明文件所述,使用 AuthSubRevokeToken 處理常式撤銷權杖。
舉例來說,如果您想以傳統工作階段的方式管理權杖,用戶端可以在使用者工作階段開始時取得權杖,並在使用者工作階段結束時撤銷權杖。
如要撤銷權杖,請在每個用戶端程式庫中使用下列項目:
Java
AuthSubUtil.revokeToken(sessionToken, null);
如果您使用安全的 AuthSub,請傳遞 RSA 私密金鑰:
AuthSubUtil.revokeToken(sessionToken, privateKey);
.NET
AuthSubUtil.revokeToken(sessionToken, null);
如果您使用安全的 AuthSub,請傳遞 RSA 私密金鑰:
AuthSubUtil.revokeToken(sessionToken, privateKey);
PHP
$wasRevoked = Zend_Gdata_AuthSub::AuthSubRevokeToken($sessionToken);如果您使用安全的 AuthSub,請傳遞 Zend_Gdata_HttpClient,以便使用 RSA 私密金鑰簽署要求:
$wasRevoked = Zend_Gdata_AuthSub::AuthSubRevokeToken($sessionToken, $client);Python
calendar_service.RevokeAuthSubToken()
其他資源和範例
- Google Data API 提示網誌上的 AuthSub 範例
- Python 用戶端程式庫 AuthSub 範例
- Java 用戶端程式庫 AuthSub 範例
- 文章:搭配 .NET 用戶端程式庫使用 AuthSub
- 文章:搭配 JavaScript 用戶端程式庫使用「AuthSub」驗證
產生自行簽署的私密金鑰和公開憑證,以搭配安全 AuthSub 使用
私密金鑰用於產生簽章,且必須隨附於每項要求。Google 會使用憑證內嵌的公開金鑰驗證簽名。公開金鑰必須是 1024 位元的 RSA 金鑰,並以 PEM 格式編碼為 X.509 憑證。註冊時,請將認證傳送給 Google。
以下各節提供範例,說明如何使用兩種特定工具 (OpenSSL 公用程式和 Java 的 keytool 公用程式) 產生金鑰和憑證。
這些範例並非 Google Data API 專用,您可以使用相同的公用程式產生任何用途的金鑰。
以下範例假設貴公司名稱為 My_Company,位於美國加州山景城,網域名稱為 example.com。
使用 OpenSSL 產生金鑰
如要建立一組 RSA 金鑰和對應的憑證,可以使用下列指令:
# Generate the RSA keys and certificate openssl req -x509 -nodes -days 365 -newkey rsa:1024 -sha1 -subj \ '/C=US/ST=CA/L=Mountain View/CN=www.example.com' -keyout \ myrsakey.pem -out /tmp/myrsacert.pem
警告:加入 -nodes 參數會建立私密金鑰,但不會設定密碼來保護金鑰。不過,為提高安全性,建議您省略這個參數。
-sha1 參數指定金鑰將用於產生 SHA1 簽章。
-subj 參數會指定憑證代表的應用程式身分。
-keyout 參數會指定包含金鑰的檔案。這個檔案包含機密資訊,請妥善保護,不要與任何人分享。
-out 參數會指定包含 PEM 格式憑證的檔案 (註冊時可傳送給 Google)。
為 .NET 用戶端產生金鑰
.NET 架構無法解讀以 PEM 格式儲存的金鑰或憑證。因此,建立 .pem 檔案後,還需要執行下列步驟:
openssl pkcs12 -export -in test_cert.pem -inkey myrsacert.pem -out myrsacert.pfx -name "Testing Certificate"
這個步驟會從私密金鑰和憑證產生 PFX 檔案。這個檔案可以匯入 .NET 用戶端程式庫,用於以數位方式簽署對 Google Data API 提出的要求。
為 Java 用戶端產生金鑰
Java 用戶端接受 PKCS#8 格式的私密金鑰。使用上述指示產生金鑰/憑證後,請從產生的 .pem 檔案建立 .pk8 檔案:
openssl pkcs8 -in myrsakey.pem -topk8 -nocrypt -out myrsakey.pk8
或者,您也可以使用 Java 金鑰儲存區和 keytool 公用程式,建立一對 RSA 金鑰和對應的憑證。使用下列指令:
# Generate the RSA keys and certificate keytool -genkey -v -alias Example -keystore ./Example.jks\ -keyalg RSA -sigalg SHA1withRSA\ -dname "CN=www.example.com, OU=Engineering, O=My_Company, L=Mountain View, ST=CA, C=US"\ -storepass changeme -keypass changeme
警告:「changeme」並非理想密碼,這只是範例。
-dname 參數會指定憑證代表的應用程式身分。-storepass 參數會指定保護 KeyStore 的密碼。-keypass 參數會指定密碼來保護私密金鑰。
如要將憑證寫入可在 ManageDomains 工具中使用的檔案,請使用下列指令:
# Output the public certificate to a file keytool -export -rfc -keystore ./Example.jks -storepass changeme \ -alias Example -file mycert.pem