Google帳戶最早用來申請巨大的Gmail郵箱(如今看來,一般個大吧),隨著后來的Blogger,Picasa,Docs等各種服務上線,也就順路繼承了過來?,F在使用一個Google帳戶,就可以同時使用這些服務。
既然我們打算寫一個從Picasa取相冊數據的Gadget,就免不了要先了解一些和Goolge帳戶有關的知識。因為Picasa的數據也是受保護的,并非誰要看都可以(公開的相冊除外哦,那都是炫耀冊,巴不得全天下人都看見呢),我們的程序也不例外,要想取到相冊的數據,程序必須向Google的服務器證明自己得到了相應用戶的授權。
一個人類用戶當然可以這樣做:打開Picasa的首頁,發現要求登錄,于是輸入自己的用戶名密碼,成功后就查看自己的相冊。我們的程序可干不了,它不會打開瀏覽器,好吧,這個它會,但打開以后它找不著用戶名的輸入框在哪,即便找到了,也不知該往里面填什么,即便填對了,也不知要看什么,即便看到了,也看不懂,即便看懂了也學不會……(讀者:你貧不貧?)
所以一切的一切都還要咱們自己來寫,當然少不了Google的幫忙。
為了方便應用程序的登錄,Google在自己的服務器上開放了被稱之為“Google Account Authentication”的服務,我們只用到其中一種方式:ClientLogin。使用這種方式訪問Google的服務大致是下面的流程:

很容易看出來,這基本上是一個兩步驟的工作:首先使用一個Google帳戶訪問Google
Account Authentication 服務,并得到一個可以合法訪問服務數據的token(Google把它叫做得到一個“授權”,不過習慣上還是叫token吧,就是令牌,拿了以后皇帝不能砍你頭的那種,此過程也叫做申請一個token);使用上一步得到的token去訪問具體的服務并取得數據(我們的例子中就是訪問Picasa服務)。
有一些東西從圖上看不出,我來說一說。一是程序訪問Gmail的時候使用的不是這種方式(畢竟Gmail太早啦,那時連Google自己都沒有考慮清楚吧),但其他大部分Goolge服務,包括Calendar,Docs,Picasa,Blogger,Contacts,Google
Apps等等,都是上面這個流程。二是并非申請了一個token以后,就可以訪問Google所有的服務,實際上需要為每個服務申請不同的token。
具體到代碼中,我們使用XmlHttpRequest對象來發送請求并且接受回傳的數據。
XmlHttpRequest是Gadget Host提供的一個類型(注意我沒有說對象,因此要用的時候你還得自己初始化,也就是new一下,哈哈),其行為與W3C所指定的標準XmlHttpRequest相同。再一次的,不要聯想到瀏覽器,你不能假設這個XmlHttpRequest與IE或者FireFox提供的XmlHttpRequest有任何聯系,更不能依賴這樣的假設來編寫程序。
好,廢話少說,還用上一節新建的“白Gadget“(笑),在main.js文件里添加這樣一個函數:
function createXhr() {
var xhr;
try {
xhr = framework.google.betaXmlHttpRequest2();
} catch (e) {
xhr = new XMLHttpRequest();
}
return xhr;
}
調用這個函數就可以得到一個XmlHttpRequest的對象啦。
然后為我們的Gadget添加一個主類,并把需要的對象引用也聲明好,這些都寫在main.js文件中,像這樣:
var xhRequest=null;
var main=new Main();
//Gadget啟動時便登錄
function view_onOpen() {
main.login();
}
function Main(){
this.albums=[];
}
//具體的登錄函數
Main.prototype.login=function(){
}
我們就要在Main.login()函數中寫我們取token的邏輯。
詳細說說申請token的過程。請求是通過XmlHttpRequest對象發起的,而對一個請求來說,最重要的信息有四個:請求的URL,請求的類型,請求頭和消息體。
URL是說你的請求要發往哪里,既然我們要使用Google的服務,那當然要往Google那里發了,具體應該為:
https://www.google.com/accounts/ClientLogin
如果你沒有看出這是一個安全的https請求,那我提醒一下(如果你看出來了,我就不提醒了,笑)。
請求的類型是指你要Google的服務器替你做什么事情,是返回你要查詢的數據?還是為你更新已有的數據,抑或僅僅是提交一些數據,還是要服務器幫你刪除一些數據?
Google的服務器通過你提交請求的類型來做相應的操作,每一種操作的類型對應如下:
- 查詢 GET
- 提交 POST
- 更新 PUT
- 刪除 DELETE
看著眼熟么?沒錯,正是輕量級的Web Service接口REST!
我們做登錄顯然是一個提交的動作,
要把我們的用戶名和密碼告訴Google,因此我們的請求類型是POST。
對登錄來說,請求頭沒有特殊要求,只需要請求頭Content-Type
,
其值為application/x-www-form-urlencoded
所需的用戶名,密碼等信息被統一稱為“屬性”,屬性的值將放在消息體中發送。因此你的消息體看起來是下面這個樣子的一個字符串:
Email=mymail2009.test%40gmail.com&Passwd=mymail2009&service=lh2&source=gd-picasa-gadget-1.0.0.0&accountType=HOSTED_OR_GOOGLE
注意其中紅色的部分,用戶名和密碼的位置你當然很容易找到,”service=lh2”這一項就指明了你要為訪問什么服務申請token,lh2是指Picasa,如果訪問Google Docs則要填writely,詳細的列表可以看這一節最后的附錄。
好,把登錄的代碼整個貼出來,你應該很容易找到以上四部分對應的地方。
Main.prototype.login=function(){
xhRequest= createXhr();
//請求的URL
var url="https://www.google.com/accounts/ClientLogin";
//消息體
var data="Email=mymail2009.test%40gmail.com&Passwd=mymail2009&service=lh2&source=gd-picasa-gadget-1.0.0.2&accountType=HOSTED_OR_GOOGLE";
xhRequest.onreadystatechange =function(){
if (!xhRequest) {
return;
}
if (xhRequest.readyState != 4) {
return;
}
//如果下面這行能夠被執行,說明登錄請求已經有數據返回
alert(“登錄動作完畢啦!”);
alert(xhRequest.responseText);
}//接受數據后的回調函數
//請求的類型,是POST
xhRequest.open('POST', url, true);
//請求頭
xhRequest.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
xhRequest.send(data);
};
在請求的回調函數中,目前只是先簡單的打印了相應的文本內容,實際上應該在這里做更多的事,詳情咱們下節再聊。如果你看到類似下面這樣的輸出內容,說明登錄的請求成功了。如果沒有成功,很可能是因為我已經換掉了用戶名和密碼,用你自己的Google帳戶試試看。
應該看到的內容:
SID=
DQAAAHYAAADYQ4hToTAEYRu0uEXP9yXZ1uc_W3-kBtZFpug78XQDGiykOb-Sv2qdXtdUOL-
npRJm9SSq-AEvSBodrcuy3UwgFM8SX_z6fXzpGaJzHzQx5YTzR0AJHCEkFh
4yOoBFs0iCE2LI0LWQs6_2BFyIuLLMwRA8m3vfuVzNE3CHjrUHZA
LSID=
DQAAAHgAAAClSiMWRfKAonW8zIytZ7NEizJNMQZojiNqsDxm3elei36MV
7GzM72bMiqdQawt8Fd1Dpp68p5bs1XYOXUPmDunUsZM1BZsAiXbIEouAJz1XjlysUQG-0p9969zYCvUm2tqWkA1BFVU2UqvjMAaBSgj10VkZzvcAbZB8nQf_mwRyg
Auth=
DQAAAHcAAAClSiMWRfKAonW8zIytZ7NEizJNMQZojiNqsDxm3elei36
MV7GzM72bMiqdQawt8FcmxySIt75kfLxcis5BZnNCsyVuCwKM-DtNZcToUtm9IWoJyvNbUD9UTFYZPdBu1OyXsfY_QJHZfZdAT2QC
cExSIYKMvLfhhit9RPz4Gk2xlQ/n
Auth那一項后面的值就是token啦,可以不被砍頭了。
附錄:已知的Google服務及服務名
Calendar
Data API
|
cl
|
Google
Base Data API
|
gbase
|
Blogger
Data API
|
blogger
|
Contacts
Data API
|
cp
|
Documents
List Data API
|
writely
|
Picasa
Web Albums Data API
|
lh2
|
Google
Apps Provisioning API
|
apps
|
Spreadsheets
Data API
|
wise
|
YouTube
Data API
|
youtube
|