这个需求来自于我最近练手的一个项目,在项目中我需要将一些自己发表的和收藏整理的网文集中到一个地方存放,如果全部采用手工操作工作量大而且繁琐,因此周公决定利用C#来实现。在很多地方都需要验证用户身份才可以进行下一步操作,这就免不了POST请求来登录,在实际过程中发现有些网站登录是HTTPS形式的,在解决过程中遇到了一些小问题,现在跟大家分享。
 通用辅助类
 下面是我编写的一个辅助类,在这个类中采用了HttpWebRequest中发送GET/HTTP/HTTPS请求,因为有的时候需要获取认证信息(如Cookie),所以返回的是HttpWebResponse对象,有了返回的HttpWebResponse实例,可以获取登录过程中返回的会话信息,也可以获取响应流。
 代码如下:

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Net.Security;
  6. using System.Security.Cryptography.X509Certificates;
  7. using System.DirectoryServices.Protocols;
  8. using System.ServiceModel.Security;
  9. using System.Net;
  10. using System.IO;
  11. using System.IO.Compression;
  12. using System.Text.RegularExpressions;
  13. /*
  14. * 作者:周公(zhoufoxcn)
  15. * 日期:2011-05-08
  16. * 原文出处:http://blog.csdn.net/zhoufoxcn 或http://zhoufoxcn.blog.51cto.com
  17. * 版权说明:本文可以在保留原文出处的情况下使用于非商业用途,周公对此不作任何担保或承诺。
  18. * */
  19. namespace BaiduCang
  20. {
  21. /// <summary>
  22. /// 有关HTTP请求的辅助类
  23. /// </summary>
  24. public class HttpWebResponseUtility
  25. {
  26. private static readonly string DefaultUserAgent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)";
  27. /// <summary>
  28. /// 创建GET方式的HTTP请求
  29. /// </summary>
  30. /// <param name="url">请求的URL</param>
  31. /// <param name="timeout">请求的超时时间</param>
  32. /// <param name="userAgent">请求的客户端浏览器信息,可以为空</param>
  33. /// <param name="cookies">随同HTTP请求发送的Cookie信息,如果不需要身份验证可以为空</param>
  34. /// <returns></returns>
  35. public static HttpWebResponse CreateGetHttpResponse(string url,int? timeout, string userAgent,CookieCollection cookies)
  36. {
  37. if (string.IsNullOrEmpty(url))
  38. {
  39. throw new ArgumentNullException("url");
  40. }
  41. HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
  42. request.Method = "GET";
  43. request.UserAgent = DefaultUserAgent;
  44. if (!string.IsNullOrEmpty(userAgent))
  45. {
  46. request.UserAgent = userAgent;
  47. }
  48. if (timeout.HasValue)
  49. {
  50. request.Timeout = timeout.Value;
  51. }
  52. if (cookies != null)
  53. {
  54. request.CookieContainer = new CookieContainer();
  55. request.CookieContainer.Add(cookies);
  56. }
  57. return request.GetResponse() as HttpWebResponse;
  58. }
  59. /// <summary>
  60. /// 创建POST方式的HTTP请求
  61. /// </summary>
  62. /// <param name="url">请求的URL</param>
  63. /// <param name="parameters">随同请求POST的参数名称及参数值字典</param>
  64. /// <param name="timeout">请求的超时时间</param>
  65. /// <param name="userAgent">请求的客户端浏览器信息,可以为空</param>
  66. /// <param name="requestEncoding">发送HTTP请求时所用的编码</param>
  67. /// <param name="cookies">随同HTTP请求发送的Cookie信息,如果不需要身份验证可以为空</param>
  68. /// <returns></returns>
  69. public static HttpWebResponse CreatePostHttpResponse(string url,IDictionary<string,string> parameters,int? timeout, string userAgent,Encoding requestEncoding,CookieCollection cookies)
  70. {
  71. if (string.IsNullOrEmpty(url))
  72. {
  73. throw new ArgumentNullException("url");
  74. }
  75. if(requestEncoding==null)
  76. {
  77. throw new ArgumentNullException("requestEncoding");
  78. }
  79. HttpWebRequest request=null;
  80. //如果是发送HTTPS请求
  81. if(url.StartsWith("https",StringComparison.OrdinalIgnoreCase))
  82. {
  83. ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(CheckValidationResult);
  84. request = WebRequest.Create(url) as HttpWebRequest;
  85. request.ProtocolVersion=HttpVersion.Version10;
  86. }
  87. else
  88. {
  89. request = WebRequest.Create(url) as HttpWebRequest;
  90. }
  91. request.Method = "POST";
  92. request.ContentType = "application/x-www-form-urlencoded";
  93. if (!string.IsNullOrEmpty(userAgent))
  94. {
  95. request.UserAgent = userAgent;
  96. }
  97. else
  98. {
  99. request.UserAgent = DefaultUserAgent;
  100. }
  101. if (timeout.HasValue)
  102. {
  103. request.Timeout = timeout.Value;
  104. }
  105. if (cookies != null)
  106. {
  107. request.CookieContainer = new CookieContainer();
  108. request.CookieContainer.Add(cookies);
  109. }
  110. //如果需要POST数据
  111. if(!(parameters==null||parameters.Count==0))
  112. {
  113. StringBuilder buffer = new StringBuilder();
  114. int i = 0;
  115. foreach (string key in parameters.Keys)
  116. {
  117. if (i > 0)
  118. {
  119. buffer.AppendFormat("&{0}={1}", key, parameters[key]);
  120. }
  121. else
  122. {
  123. buffer.AppendFormat("{0}={1}", key, parameters[key]);
  124. }
  125. i++;
  126. }
  127. byte[] data = requestEncoding.GetBytes(buffer.ToString());
  128. using (Stream stream = request.GetRequestStream())
  129. {
  130. stream.Write(data, 0, data.Length);
  131. }
  132. }
  133. return request.GetResponse() as HttpWebResponse;
  134. }
  135. private static bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors)
  136. {
  137. return true; //总是接受
  138. }
  139. }
  140. }

从上面的代码中可以看出POST数据到HTTP和HTTPS站点不同,POST数据到HTTPS站点的时候需要设置ServicePointManager类的ServerCertificateValidationCallback属性,并且在POST到https://passport.baidu.com/?login时还需要将HttpWebResquest实例的ProtocolVersion属性设置为HttpVersion.Version10(这个未验证是否所有的HTTPS站点都需要设置),否则在调用GetResponse()方法时会抛出“基础连接已经关闭: 连接被意外关闭。”的异常。
 
 用法举例
 这个类用起来也很简单:
 (1)POST数据到HTTPS站点,用它来登录百度:

  1. string loginUrl = "https://passport.baidu.com/?login";
  2. string userName = "userName";
  3. string password = "password";
  4. string tagUrl = "http://cang.baidu.com/"+userName+"/tags";
  5. Encoding encoding = Encoding.GetEncoding("gb2312");
  6. IDictionary<string, string> parameters = new Dictionary<string, string>();
  7. parameters.Add("tpl", "fa");
  8. parameters.Add("tpl_reg", "fa");
  9. parameters.Add("u", tagUrl);
  10. parameters.Add("psp_tt", "0");
  11. parameters.Add("username", userName);
  12. parameters.Add("password", password);
  13. parameters.Add("mem_pass", "1");
  14. HttpWebResponse response = HttpWebResponseUtility.CreatePostHttpResponse(loginUrl, parameters, null, null, encoding, null);
  15. string cookieString = response.Headers["Set-Cookie"];

(2)发送GET请求到HTTP站点
 在cookieString中包含了服务器端返回的会话信息数据,从中提取了之后可以设置Cookie下次登录时带上这个Cookie就可以以认证用户的信息,假设我们已经登录成功并且获取了Cookie,那么发送GET请求的代码如下:

  1. string userName = "userName";
  2. string tagUrl = "http://cang.baidu.com/"+userName+"/tags";
  3. CookieCollection cookies = new CookieCollection();//如何从response.Headers["Set-Cookie"];中获取并设置CookieCollection的代码略
  4. response = HttpWebResponseUtility.CreateGetHttpResponse(tagUrl, null, null, cookies);

(3)发送POST请求到HTTP站点
 以登录51CTO为例:

  1. string loginUrl = "http://home.51cto.com/index.php?s=/Index/doLogin";
  2. string userName = "userName";
  3. string password = "password";
  4. IDictionary<string, string> parameters = new Dictionary<string, string>();
  5. parameters.Add("email", userName);
  6. parameters.Add("passwd", password);
  7. HttpWebResponse response = HttpWebResponseUtility.CreatePostHttpResponse(loginUrl, parameters, null, null, Encoding.UTF8, null);

在这里说句题外话,CSDN的登录处理是由http://passport.csdn.net/ajax/accounthandler.ashx这个Handler来处理的。
 
 总结
在本文只是讲解了在C#中发送请求到HTTP和HTTPS的用法,分GET/POST两种方式,为减少一些繁琐和机械的编码,周公将其封装为一个类,发送数据之后返回HttpWebResponse对象实例,利用这个实例我们可以获取服务器端返回的Cookie以便用认证用户的身份继续发送请求,或者读取服务器端响应的内容,不过在读取响应内容时要注意响应格式和编码,本来在这个类中还有读取HTML和WML内容的方法(包括服务器使用压缩方式传输的数据),但限于篇幅和其它方面的原因,此处省略掉了。如有机会,在以后的文章中会继续讲述这方面的内容。
 
 周公
 2011-05-08

在C#用HttpWebRequest中发送GET/HTTP/HTTPS请求相关推荐

  1. qt5中服务器文件传输,POST在Qt5中发送JSON文件的请求

    在Qt5的帮助下,通过POST请求将JSON文件发送到服务器时有点问题.我给你一张我的程序:POST在Qt5中发送JSON文件的请求 #include #include #include #inclu ...

  2. httpsrequest java_java 发送http和https请求的实例

    HTTP请求: 如果需要Json格式的自己转下,度娘上N种姿势- //处理http请求 requestUrl为请求地址 requestMethod请求方式,值为"GET"或&quo ...

  3. java请求参数_在Java中发送http的post请求,设置请求参数等等

    前几天做了一个定时导入数据的接口,需要发送http请求,第一次做这种的需求,特地记一下子, 导包 import java.text.SimpleDateFormat; import java.util ...

  4. 发送http和https请求工具类 Json封装数据

    在一些业务中我们可要调其他的接口(第三方的接口) 这样就用到我接下来用到的工具类. 用这个类需要引一下jar包的坐标 <dependency><groupId>org.jsou ...

  5. HttpClient 发送 HTTP、HTTPS 请求的简单封装

    序 近期这几周.一直在忙同一个项目.刚開始是了解需求.需求有一定了解之后,就開始调第三方的接口.因为第三方给提供的文档非常模糊,在调接口的时候,出了非常多问题,一直在沟通协调,详细的无奈就不说了,因为 ...

  6. C# HttpWebRequest GET HTTP HTTPS 请求

    这个需求来自于我最近练手的一个项目,在项目中我需要将一些自己发表的和收藏整理的网文集中到一个地方存放,如果全部采用手工操作工作量大而且繁琐,因此周公决定利用C#来实现.在很多地方都需要验证用户身份才可 ...

  7. 如何在WinForm中发送HTTP请求

    Winform窗体中发送HTTP请求 手工发送HTTP请求主要是调用 System.Net的HttpWebResponse方法 手工发送HTTP的GET请 求: 1 string strURL = & ...

  8. 如何在HTTP POST请求中发送参数?

    本文翻译自:How are parameters sent in an HTTP POST request? In an HTTP GET request, parameters are sent a ...

  9. net类库中发送电子邮件的方法总结

    发送电子邮件是许多需要用户注册的网站的通用功能,通过正则表达式我们可以过滤掉不符合电子邮件格式的输入,但是仍没有办法确保用户填写的电子邮件地址一定是他本人真实有效的电子邮件地址,通常验证电子邮件真实有 ...

最新文章

  1. Knockout 监控数组对象属性
  2. python十二:字符串格式化
  3. UA MATH563 概率论的数学基础 中心极限定理4 独立一元随机变量的性质
  4. leetcode 236. 二叉树的最近公共祖先 递归解法 c语言
  5. java面试题大合集(开发者必看一)
  6. Http和Socket连接区别
  7. mysql 新增返回主键自增id_详解mysql插入数据后返回自增ID的七种方法
  8. mysql 存储过程 条件_如何在MySQL存储过程中正确实现条件?
  9. java list按多个字段排序_java 对象List按照多个字段进行排序
  10. POJ3264 Balanced Lineup【线段树】
  11. [转载] Python的双端队列deque
  12. Python基础教程---读书笔记一
  13. 华为android强刷系统下载地址,华为C8815官方rom固件刷机包下载_华为C8815系统强刷升级包...
  14. 浅析redis雪崩击穿和穿透
  15. 《古诗词-劝学惜时大全》
  16. Using the Hardware Scaler for Performance and Efficiency
  17. java普通分隔符,懂得java的文件4种分隔符
  18. 8.微信小程序-Mobx数据共享(类似vuex)
  19. Tensorflow五种花卉分类
  20. 工信部python证书多少钱_python requests SSL证书问题

热门文章

  1. 从jvm角度看懂类初始化、方法重写、重载。
  2. 如何快速实现物联网行业中的实名认证
  3. 极光API推送 (v3 版本)
  4. CentOS7关闭防火墙方法
  5. windows 64位 dll文件 位置及python包rtree shapely安装
  6. redis(二)redis实战 使用redis进行文章的排序
  7. ubuntu 14.04服务器上使用nginx搭建wordpress博客详解
  8. JSP中文乱码问题解决
  9. Windows Sockets2 详解2——堵塞与非堵塞模式
  10. 对计算机科学技术的看法