Google帳戶最早用來申請巨大的Gmail郵箱(如今看來,一般個大吧),隨著后來的Blogger,PicasaDocs等各種服務上線,也就順路繼承了過來?,F在使用一個Google帳戶,就可以同時使用這些服務。

既然我們打算寫一個從Picasa取相冊數據的Gadget,就免不了要先了解一些和Goolge帳戶有關的知識。因為Picasa的數據也是受保護的,并非誰要看都可以(公開的相冊除外哦,那都是炫耀冊,巴不得全天下人都看見呢),我們的程序也不例外,要想取到相冊的數據,程序必須向Google的服務器證明自己得到了相應用戶的授權。

一個人類用戶當然可以這樣做:打開Picasa的首頁,發現要求登錄,于是輸入自己的用戶名密碼,成功后就查看自己的相冊。我們的程序可干不了,它不會打開瀏覽器,好吧,這個它會,但打開以后它找不著用戶名的輸入框在哪,即便找到了,也不知該往里面填什么,即便填對了,也不知要看什么,即便看到了,也看不懂,即便看懂了也學不會……(讀者:你貧不貧?)

所以一切的一切都還要咱們自己來寫,當然少不了Google的幫忙。

為了方便應用程序的登錄,Google在自己的服務器上開放了被稱之為“Google Account Authentication”的服務,我們只用到其中一種方式:ClientLogin。使用這種方式訪問Google的服務大致是下面的流程:


很容易看出來,這基本上是一個兩步驟的工作:首先使用一個Google帳戶訪問Google Account Authentication 服務,并得到一個可以合法訪問服務數據的tokenGoogle把它叫做得到一個“授權”,不過習慣上還是叫token吧,就是令牌,拿了以后皇帝不能砍你頭的那種,此過程也叫做申請一個token);使用上一步得到的token去訪問具體的服務并取得數據(我們的例子中就是訪問Picasa服務)。

有一些東西從圖上看不出,我來說一說。一是程序訪問Gmail的時候使用的不是這種方式(畢竟Gmail太早啦,那時連Google自己都沒有考慮清楚吧),但其他大部分Goolge服務,包括Calendar,Docs,Picasa,Blogger,Contacts,Google Apps等等,都是上面這個流程。二是并非申請了一個token以后,就可以訪問Google所有的服務,實際上需要為每個服務申請不同的token。

具體到代碼中,我們使用XmlHttpRequest對象來發送請求并且接受回傳的數據。

XmlHttpRequestGadget Host提供的一個類型(注意我沒有說對象,因此要用的時候你還得自己初始化,也就是new一下,哈哈),其行為與W3C所指定的標準XmlHttpRequest相同。再一次的,不要聯想到瀏覽器,你不能假設這個XmlHttpRequestIE或者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