软件开发
开发分享
软件下载

利用Google Docs实现网盘功能——身份验证篇

时间:2010-07-14 来源:juhe99 点击量:

利用Google Docs实现网盘功能——身份验证篇

一直以来想要做个程序,将Google Docs用作网盘,程序做得差不多了才发现不是所有的人都可以上传任意类型的文件,只有商业用户才可以。商业用户是要交钱的,这与我们倡导的免费精神相去甚远。怎么办?我的心血不能白费,Google还算厚道没有把门关死,可以通过form的形式上传,我们可以模拟form的动作,就能上传了。

Google在上传时要进行身份验证。取得身份验证后,提出上传要求,这时返回一个上传地址,然后上传文件。下面一步步来:

身份验证流程

  1. 访问Google Docs获取登录页面:        先访问 http://docs.google.com,它通过自动跳转将你带到一个登录页面。按登录页面中的头部的set-cookie设置HttpWebRequest的cookie,cookie中最重要的是HSID。

  2. 提交登录信息:        设置url为 https://www.google.com/accounts/ServiceLoginAuth?service=writely,然后设置提交数据:                    ltmpl=homepage&continue=http://docs.google.com/&followup=http://docs.google.com/&service=writely&nui=1&rm=false&dsh={0}&ltmpl=homepage&ltmpl=homepage&GALX={1}&Email={2}&Passwd={3}&rmShown=1&signIn=登录&asts=                其中Email填Google帐户名,Passwd填密码,GALX可以从cookie中找到,dsh可从页面的数据中得到。

  3. 检查Cookie:        访问网址:https://www.google.com/accounts/CheckCookie,取得下一步的访问地址。

  4. 获取认证Cookie:        访问网址:http://docs.google.com/?auth=.......,根据回应设置cookie,这时的cookie就是可以访问相当于doc api中的token了。

关键Cookie:认证后的cookie中包含三条记录HSID、SID、writelySID

核心代码实现

private CookieContainer GetAuthenticationCookie(string User,string Passwd)
{
    string GALX;
    string dsh;
    string resText = "";
    CookieContainer Auth = new CookieContainer();
    
    //第一步:访问docs.google.com获取登录页面
    HttpWebRequest req = CreatRequest("http://docs.google.com/");
    req.Method = "POST";
    req.ContentLength = 0;
    HttpWebResponse res = (HttpWebResponse)req.GetResponse();
    
    //第二步:提取GALX和dsh参数,构造登录数据
    resText = getResponseText(res);
    GALX = resText.Substring(resText.IndexOf("GALX") + 26, 11);
    if ((resText.Substring(resText.IndexOf("dsh") + 32, 1)) == "-")
        dsh = resText.Substring(resText.IndexOf("dsh") + 32, 20);
    else
        dsh = resText.Substring(resText.IndexOf("dsh") + 32, 19);
        
    string postData = string.Format(
        "ltmpl=homepage&continue=http://docs.google.com/&followup=http://docs.google.com/&service=writely&nui=1&rm=false&dsh={0}&ltmpl=homepage&ltmpl=homepage&GALX={1}&Email={2}&Passwd={3}&rmShown=1&signIn=登录&asts=",
        dsh, GALX, User, Passwd);
        
    req = CreatRequest("https://www.google.com/accounts/ServiceLoginAuth?service=writely");
    req.AllowAutoRedirect = false;
    req.Method = "POST";
    
    //设置cookie及提交数据
    Auth.Add(setCookie(res, "www.google.com"));
    req.CookieContainer = Auth;
    setPostData(req, postData);
    res = (HttpWebResponse)req.GetResponse();
    
    //第三步:检查Cookie
    req = CreatRequest(res.Headers["Location"]);
    Auth.Add(setCookie(res, "www.google.com"));
    req.CookieContainer = Auth;
    res = (HttpWebResponse)req.GetResponse();
    
    //第四步:获取最终认证Cookie
    resText = getResponseText(res);
    string url = resText.Substring(resText.IndexOf("url=")).Split('"')[0];
    url = HttpUtility.HtmlDecode(url);
    url = url.Substring(5, url.Length - 6);
    req = CreatRequest(url);
    req.Method = "GET";
    req.AllowAutoRedirect = false;
    Auth.Add(setCookie(res, "www.google.com"));
    req.CookieContainer = Auth;
    res = (HttpWebResponse)req.GetResponse();
    Auth.Add(setCookie(res, "www.google.com"));
    
    return Auth;
}

HTTPS调试注意事项

整个过程很简单,但调试花了很长时间,主要是在HTTPS下调试走了很多弯路。一开始使用HttpAnalyzer,结果有bug显示的传送数据总是重复。后来还是使用Fiddler才解决。但使用Fiddler时在HTTPS下会出现证书与网站不符的错误。

解决办法:

ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(ValidateServerCertificate);

public static bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
    return true;
}

重要提示:

  • 第一个函数在设置HttpWebRequest时调用就不会出现错误了