Google帐户最早用来申请巨大的Gmail邮箱(如今看来,一般个大吧),随着后来的BloggerPicasaDocs等各种服务上线,也就顺路继承了过来。现在使用一个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这一项就指明了你要为访问什么服务申请tokenlh2是指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