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。
代码写得很笨拙,大家不吝赐教。
下一步,研究上传任意文件至指定目录。

转载于:https://www.cnblogs.com/zcmky/archive/2010/04/02/1703397.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/263972.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java string fill_Java使用fill()数组填充的实现

Arrays 类提供了一个 fill() 方法&#xff0c;可以在指定位置进行数值填充。fill() 方法虽然可以填充数组&#xff0c;但是它的功能有限制&#xff0c;只能使用同一个数值进行填充。语法如下&#xff1a;声明举例&#xff1a;public static void fill(int[] a, form, to, int v…

FL-EM7688 Smart评估板openwrt开发环境搭建(linux固件部分)

搭建前先阅读原厂文档\FL-EM7688 Smart V1.0评估板1资料\文档\FL-EM7688 Smart评估板使用说明.pdf 1.根据FL-EM7688 Smart评估板使用说明.pdf安装好串口调试工具&#xff0c;以及实现通过网线更新固件 2.安装虚拟机&#xff08;版本号12.56&#xff09;和ubuntu-16.04.3-deskto…

小型公司如何管理

一直以来&#xff0c;人们对大型公司的管理都非常称道&#xff0c;对小型公司的管理都认为比较简单。这话说得有一定的道理&#xff0c;毕竟小型公司的人比较少&#xff0c;相对来说&#xff0c;管理的范围和直径比较小一些&#xff0c;能比较有效地执行和监管。但是&#xff0…

堆栈溢出从入门到提高

转自&#xff1a;http://www.jiaonan.net/html/2007/06/20070624034620915.htm 入门篇 2007-6-24 15:46:20 本讲的预备知识&#xff1a; 首先你应该了解intel汇编语言&#xff0c;熟悉寄存器的组成和功能。你必须有堆栈和存储分配方面 的基础知识&#xff0c;有关这方面的计…

java replaceall函数_JAVA中string.replace和string.replaceAll的区别及用法

展开全部JAVA中string.replace()和string.replaceAll()的区别及用法乍一看&#xff0c;字面上理解好像replace只替换第一个出现的字符(受javascript的影响)&#xff0c;32313133353236313431303231363533e59b9ee7ad9431333361313836replaceall替换所有的字符&#xff0c;其实大…

Linux之RPM 软件管理程序

RPM RPM是软件管理程序&#xff0c;提供软件的安装、升级、查询、反安装的功能。优点&#xff1a;a、安装方便&#xff0c;软件中所有数据都经过编译和打包b、查询、升级、反安装方便缺点&#xff1a;a、缺乏灵活性b、存在相依属性 用法&#xff1a; rpm 参数 软件包 指令选…

快意人生

仁者不忧&#xff0c; 智者不惑。 勇者不惧&#xff0c; 信者不悔&#xff1b; 锐气藏于胸&#xff0c; 和气浮于面&#xff0c; 才气见于事&#xff0c; 义气施于人&#xff1b; 有为有不为&#xff0c; 知足知不足&#xff01; 转载于:https://www.cnblogs.com/freeton/archi…

DOM Element

特点&#xff1a; 1. nodeType 的值为1. 2. nodeName 的值为元素的标签名(大写); 3. nodeValue 的值为null. 4. parentNode 可能是Element、Text、Comment、ProcessingInstruction、CDATASection、EntityReference。 例&#xff1a; <div id"div1">hha</di…

java filefilter的用法_Java File.listFiles(FileFilter filter)方法

Java Java File.listFiles(FileFilter filter)方法具有以下语法。public File [] listFiles(FileFilter filter)示例在下面的代码显示如何使用File.listFiles(FileFilter filter)方法。import java.io.File;import java.io.FileFilter;public class Main {public static void m…

7-5.11

连接redisr redis.Redis(host118.24.3.40,passwordHK139bc&*,db13,decode_responsesTrue)r.set(lidandan,haha’)发邮件&#xff1a;import yagmaillyagmall.SMTP(user password授权码 host)yagmall(to cc subject contens attachments附件&#xff0c;绝对路径) __ma…

c# 简单序列化

序列化&#xff1a;是将对象状态转换为可保持或传输的格式的过程&#xff0c;原因有两个&#xff0c;第一是想永久的保存这些数据&#xff0c;以便将来可以重建这些数据。第二是想把数据从一个应用程序域发送到另外一个应用程序域中去。反序列化&#xff1a;就是把存储介质中的…

.net WebApi 开发中某些注意事项

目前在做.net开发。 需要开发一套webapi. 这里记录一下某些注意点。 1. 如何开启跨域 如果webapi的用户是域外用户&#xff0c;则需要根据需要开放跨域。 首先安装Install-Package Microsoft.AspNet.WebApi.Cors 在WebApiConfig.cs里开启config.EnableCors(); 可以控制开放的范…

laravel框架中引入Workerman

1.安装Workerman 首先在laravel根目录下安装Workerman 命令:$ composer require workerman/gateway-worker 2.创建 Workerman 启动文件 创建一个 artisan 命令行工具来启动 Socket 服务端&#xff0c;在 app/Console/Commands 目录下建立命令行文件。 <?php namespaceApp\C…

java扫描指定package注解_java随笔-扫描使用指定注解的类与方法

前几天项目中让扫描出所有使用Restful API的方法。刚开始还想着用python过滤关键字来查找的&#xff0c;后来想想可以使用反射来搞的。主要包含以下三个步骤&#xff1a;根据包名解析包的具体路径查找指定包下指定注解的类在上一步骤中得到的类中&#xff0c;依次扫描包含指定注…

windows mobile开发循序渐进(6)windows mobile device center 使用问题

由于个人中邪&#xff0c;在经历一次windows 7安装失败之后&#xff0c;贼心不死&#xff0c;于昨天又重新安装了windows 7&#xff0c;终于成功。 回到windows mobile的开发上来呢&#xff0c;首先是配置环境&#xff0c;按照之前的经验&#xff0c;比较顺利的安装了virtual p…

Python---基础---list(列表)

2019-05-20 一、 # append() 向列表末尾追加新元素 返回值Nonelist1 [1,2,3,4,5]print(id(list1))list1.append(6)print(id(list1)) 二、 #copy() 复制列表list1 [1,2,3,4,5]list2 list1.copy()print(list2)print(id(list1))print(id(list2)) 三、 #count() 计算某个元素…

mysql if selected_初识MySQL

安装下载地址&#xff1a;https://dev.mysql.com/downloads/mysql/​dev.mysql.com双击.msi文件开始安装&#xff0c;采用Custom安装方式。配置安装完毕弹出配置&#xff0c;或者安装路径下bin文件夹下MySQLInstanceConfig.exe运行可以进行配置。采用Detailed Configuration-》…

VisualC++2010系列课程

VisualC2010系列课程&#xff0c; 请访问博客http://blog.csdn.net/yincheng01 &#xff08;基于Visual C2010与windows SDK fo windows7开发Windows 7超级任务栏应用程序http://blog.csdn.net/yincheng01/archive/2009/12/27/5086755.aspx基于Visual C2010与windows SDK fo wi…

【MongoDB学习笔记21】MongoDB的复合索引

索引的值是按照一定顺序排列的&#xff0c;因此使用索引键对文档进行搜索排序比较快&#xff1b;但是只有首先使用索引进行排序时&#xff0c;索引才有用&#xff1b;例如下面的排序里&#xff0c;“username”上的索引就没有起作用&#xff1a;> db.users.find().sort({&qu…

mysql 代理 a_Keepalived+Mysql+Haproxy

#dd dd0 配主从vi /etc/my.cnf[mysqld]server-id 1log-bin mysql-binbinlog-ignore-db mysql,information_schemabinlog_format mixedauto-increment-increment 2auto-increment-offset 1#ddgrant replication slave on *.* to dd192.168.55.% identified by 123456show …