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

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

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

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

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


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

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

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

XmlHttpRequestGadget Host提供的一個類型(注意我沒有說對象,因此要用的時候你還得自己初始化,也就是new一下,哈哈),其行為與W3C所指定的標(biāo)準(zhǔn)XmlHttpRequest相同。再一次的,不要聯(lián)想到瀏覽器,你不能假設(shè)這個XmlHttpRequestIE或者FireFox提供的XmlHttpRequest有任何聯(lián)系,更不能依賴這樣的假設(shè)來編寫程序。

好,廢話少說,還用上一節(jié)新建的“白Gadget“(笑),在main.js文件里添加這樣一個函數(shù):


function createXhr() {

 
var xhr;

 
try {

    xhr 
= framework.google.betaXmlHttpRequest2();

 } 
catch (e) {

    xhr 
= new XMLHttpRequest();

 }

 
return xhr;

}

調(diào)用這個函數(shù)就可以得到一個XmlHttpRequest的對象啦。

然后為我們的Gadget添加一個主類,并把需要的對象引用也聲明好,這些都寫在main.js文件中,像這樣:


var xhRequest=null;

var main=new Main();

      
//Gadget啟動時便登錄

function view_onOpen() {

            main.login();

}

function Main(){

            
this.albums=[];

}

//具體的登錄函數(shù)

Main.prototype.login
=function(){

}

我們就要在Main.login()函數(shù)中寫我們?nèi)?/span>token的邏輯。

詳細(xì)說說申請token的過程。請求是通過XmlHttpRequest對象發(fā)起的,而對一個請求來說,最重要的信息有四個:請求的URL,請求的類型,請求頭和消息體。

URL是說你的請求要發(fā)往哪里,既然我們要使用Google的服務(wù),那當(dāng)然要往Google那里發(fā)了,具體應(yīng)該為:

https://www.google.com/accounts/ClientLogin

如果你沒有看出這是一個安全的https請求,那我提醒一下(如果你看出來了,我就不提醒了,笑)。

請求的類型是指你要Google的服務(wù)器替你做什么事情,是返回你要查詢的數(shù)據(jù)?還是為你更新已有的數(shù)據(jù),抑或僅僅是提交一些數(shù)據(jù),還是要服務(wù)器幫你刪除一些數(shù)據(jù)?

Google的服務(wù)器通過你提交請求的類型來做相應(yīng)的操作,每一種操作的類型對應(yīng)如下:

  •  查詢  GET
  •  提交  POST
  •  更新  PUT
  •  刪除  DELETE

看著眼熟么?沒錯,正是輕量級的Web Service接口REST

我們做登錄顯然是一個提交的動作, 要把我們的用戶名和密碼告訴Google因此我們的請求類型是POST

對登錄來說,請求頭沒有特殊要求,只需要請求頭Content-Type其值為application/x-www-form-urlencoded

所需的用戶名,密碼等信息被統(tǒng)一稱為“屬性”,屬性的值將放在消息體中發(fā)送。因此你的消息體看起來是下面這個樣子的一個字符串:

Email=mymail2009.test%40gmail.com&Passwd=mymail2009&service=lh2&source=gd-picasa-gadget-1.0.0.0&accountType=HOSTED_OR_GOOGLE

注意其中紅色的部分,用戶名和密碼的位置你當(dāng)然很容易找到,service=lh2這一項(xiàng)就指明了你要為訪問什么服務(wù)申請tokenlh2是指Picasa,如果訪問Google Docs則要填writely,詳細(xì)的列表可以看這一節(jié)最后的附錄。

好,把登錄的代碼整個貼出來,你應(yīng)該很容易找到以上四部分對應(yīng)的地方。


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;

           }

           
//如果下面這行能夠被執(zhí)行,說明登錄請求已經(jīng)有數(shù)據(jù)返回

           alert(“登錄動作完畢啦!”);

           alert(xhRequest.responseText);

      }
//接受數(shù)據(jù)后的回調(diào)函數(shù)

      
//請求的類型,是POST

      xhRequest.open('POST', url, 
true);

      
//請求頭

      xhRequest.setRequestHeader(
"Content-Type","application/x-www-form-urlencoded");

      xhRequest.send(data);

};

在請求的回調(diào)函數(shù)中,目前只是先簡單的打印了相應(yīng)的文本內(nèi)容,實(shí)際上應(yīng)該在這里做更多的事,詳情咱們下節(jié)再聊。如果你看到類似下面這樣的輸出內(nèi)容,說明登錄的請求成功了。如果沒有成功,很可能是因?yàn)槲乙呀?jīng)換掉了用戶名和密碼,用你自己的Google帳戶試試看。

應(yīng)該看到的內(nèi)容:

SID

DQAAAHYAAADYQ4hToTAEYRu0uEXP9yXZ1uc_W3-kBtZFpug78XQDGiykOb-Sv2qdXtdUOL-
npRJm9SSq-AEvSBodrcuy3UwgFM8SX_z6fXzpGaJzHzQx5YTzR0AJHCEkFh
4yOoBFs0iCE2LI0LWQs6_2BFyIuLLMwRA8m3vfuVzNE3CHjrUHZA

LSID

DQAAAHgAAAClSiMWRfKAonW8zIytZ7NEizJNMQZojiNqsDxm3elei36MV
7GzM72bMiqdQawt8Fd1Dpp68p5bs1XYOXUPmDunUsZM1BZsAiXbIEouAJz1XjlysUQG-0p9969zYCvUm2tqWkA1BFVU2UqvjMAaBSgj10VkZzvcAbZB8nQf_mwRyg

Auth

DQAAAHcAAAClSiMWRfKAonW8zIytZ7NEizJNMQZojiNqsDxm3elei36
MV7GzM72bMiqdQawt8FcmxySIt75kfLxcis5BZnNCsyVuCwKM-DtNZcToUtm9IWoJyvNbUD9UTFYZPdBu1OyXsfY_QJHZfZdAT2QC
cExSIYKMvLfhhit9RPz4Gk2xlQ/n

Auth那一項(xiàng)后面的值就是token啦,可以不被砍頭了。

附錄:已知的Google服務(wù)及服務(wù)名

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