Google帐户最早用来申请巨大的Gmail邮箱(如今看来,一般个大吧),随着后来的Blogger,Picasa,Docs等各种服务上线,也就顺路继承了过来。现在使用一个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
|