• Google Doc API研究之一:模拟页面上传任意类型文件


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

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

    第一步,通过网页访问DOC,其身份认证是通过cookie进行的,取得cookie的过程是

    1、先访问http://docs.google.com,它通过自动跳转将你带到一个登录页面。按登录页面中的头部的set- cookie设置httpwebrequest的cookie,cookie中最重要的是HSID,然后设置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}& amp;Email={2}&Passwd={3}&rmShown=1&signIn=登录&asts=

    其中Email填google帐户名,passwd填密码,GALX可以从cookie中找到,dsh可从页面的数据中得到。

    2、再访问网址:https://www.google.com/accounts /CheckCookie?continue=http%3A%2F%2Fdocs.google.com%2F&followup=http %3A%2F%2Fdocs.google.com%2F&service=writely&ltmpl=homepage& chtml=LoginDoneHtml,取得下一步的访问地址,

    3、再访问网 址:http://docs.google.com/?auth=.......,根据回应设置cookie,这时的cookie就是可以访问相当于 doc api中的token了。cookie中包含三条记录HSI,SID,writelySID。

    下面是原程序:


    private CookieContainer  GetAuthenticationCookie(string User,string Passwd)
            {

                string GALX;
                string dsh;
                string resText = "";
                CookieContainer Auth = new CookieContainer();

                //第一步
                HttpWebRequest req = CreatRequest("http://docs.google.com/");
                req.Method = "POST";
                req.ContentLength = 0;
                HttpWebResponse res = (HttpWebResponse)req.GetResponse();

                //第二步
                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}& amp; amp;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();

                //第三步

                req = CreatRequest(res.Headers["Location"]);
                Auth.Add(setCookie(res, "www.google.com"));
                req.CookieContainer = Auth;
                res = (HttpWebResponse)req.GetResponse();

                //第四步
                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;
            }

            private string getResponseText(HttpWebResponse res)
            {
                if (res.StatusCode != HttpStatusCode.OK)
                    return null;
                Stream dataStream = res.GetResponseStream();
                StreamReader reader = new StreamReader(dataStream);
                string str = reader.ReadToEnd();
                reader.Close();
                return str;
            }


            /// <summary>
            ///设置传送的数据
            /// </summary>
            /// <param name="req">The req.</param>
            /// <param name="postData">The post data.</param>
            private void setPostData(HttpWebRequest req, string postData)
            {
                byte[] bytes = Encoding.UTF8.GetBytes(postData);
                req.ContentLength = bytes.Length;

                using (Stream dataStream = req.GetRequestStream())
                {
                    dataStream.Write(bytes, 0, bytes.Length);
                    dataStream.Close();
                }

            }

            /// <summary>
            /// 根据response中头部的set-cookie对request中的cookie进行设置
            /// </summary>
            /// <param name="setCookie">The set cookie.</param>
            /// <param name="defaultDomain">The default domain.</param>
            /// <returns></returns>
            private CookieCollection setCookie(HttpWebResponse res, string defaultDomain)
            {
                string[] setCookie = res.Headers.GetValues("Set-Cookie");

                // there is bug in it,the datetime in "set-cookie" will be sepreated in two pieces.
                List<string> a = new List<string>(setCookie);
                for (int i = setCookie.Length - 1; i > 0; i--)
                {
                    if (a[i].Substring(a[i].Length - 3) == "GMT")
                    {
                        a[i - 1] = a[i - 1] + ", " + a[i];
                        a.RemoveAt(i);
                        i--;
                    }
                }
                setCookie = a.ToArray<string>();
                CookieCollection cookies = new CookieCollection();
                foreach (string str in setCookie)
                {
                    NameValueCollection hs = new NameValueCollection();
                    foreach (string i in str.Split(';'))
                    {
                        int index = i.IndexOf("=");
                        if (index > 0)
                            hs.Add(i.Substring(0, index), i.Substring(index + 1));
                        else
                            switch (i)
                            {
                                case "HttpOnly":
                                    hs.Add("HttpOnly", "True");
                                    break;
                                case "Secure":
                                    hs.Add("Secure", "True");
                                    break;
                            }
                    }
                    Cookie ck = new Cookie();
                    foreach (string Key in hs.AllKeys)
                    {
                        switch (Key)
                        {
                            case "Path":
                                ck.Path = hs[Key];
                                break;
                            case "Expires":
                                ck.Expires = DateTime.Parse(hs[Key]);
                                break;
                            case "Domain":
                                ck.Domain = hs[Key];
                                break;
                            case "HttpOnly":
                                ck.HttpOnly = true;
                                break;
                            case "Secure":
                                ck.Secure = true;
                                break;
                            default:
                                ck.Name = Key;
                                ck.Value = hs[Key];
                                break;
                        }
                    }
                    if (ck.Domain == "") ck.Domain = defaultDomain;
                    if (ck.Name != "") cookies.Add(ck);
                }
                return cookies;
            }

            /// <summary>
            /// 对request进行基本的设置
            /// </summary>
            /// <param name="URL">The URL.</param>
            /// <returns></returns>
            private HttpWebRequest CreatRequest(string URL)
            {
                HttpWebRequest req = (HttpWebRequest)WebRequest.Create(URL);
                req.UserAgent = "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.2.2) Gecko/20100316 Firefox/3.6.2";
                req.ServicePoint.Expect100Continue = false;
                req.ContentType = "application/x-www-form-urlencoded";

                return req;
            }

    整个过程很简单,但调试花了我很长时间,主要是在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;
            }
    第 一个函数在设置httpwebquest时调用就不会出现错误了。这时就可以用fiddler捕获https包了。今天就写到这里。
    这里有几点猜 想未证实,授权cookie中的writelySID及SID可能与google 的client的LSID和SID相同,但HSID不知从何而来。
    cookie 可以反复使用,不用每次对话都要取得cookie。
    代码写得很笨拙,大家不吝赐教。
    下一步,研究上传任意文件至指定目录。
  • 相关阅读:
    可能不知道的C#特性
    设计模式の依赖注入
    How to find WWN and WWPN of HBA card in Linux
    fio IO测试工具
    centos/redhat 多路径存储使用 客户端
    centos/redhat 系统误删除逻辑卷之后如何恢复
    How to use lspci, lsscsi, lsusb, and lsblk to get Linux system devices information
    How to Check and Repair EXT4 Filesystem in Linux
    如何在 Linux 上扫描/检测新的 LUN 和 SCSI 磁盘
    小程序开发知识点总结归纳
  • 原文地址:https://www.cnblogs.com/zcmky/p/1703397.html
Copyright © 2020-2023  润新知