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

using System;
using System.Collections.Generic;
using System.Linq; using System.Text; using System.Net.Security; using System.Security.Cryptography.X509Certificates; using System.DirectoryServices.Protocols; using System.ServiceModel.Security; using System.Net; using System.IO; using System.IO.Compression; using System.Text.RegularExpressions; namespace BaiduCang { /// <summary> /// 有关HTTP请求的辅助类 /// </summary> public class HttpWebResponseUtility { 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)"; /// <summary> /// 创建GET方式的HTTP请求 /// </summary> /// <param name="url">请求的URL</param> /// <param name="timeout">请求的超时时间</param> /// <param name="userAgent">请求的客户端浏览器信息,可以为空</param> /// <param name="cookies">随同HTTP请求发送的Cookie信息,如果不需要身份验证可以为空</param> /// <returns></returns> public static HttpWebResponse CreateGetHttpResponse(string url,int? timeout, string userAgent,CookieCollection cookies) { if (string.IsNullOrEmpty(url)) { throw new ArgumentNullException("url"); } HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest; request.Method = "GET"; request.UserAgent = DefaultUserAgent; if (!string.IsNullOrEmpty(userAgent)) { request.UserAgent = userAgent; } if (timeout.HasValue) { request.Timeout = timeout.Value; } if (cookies != null) { request.CookieContainer = new CookieContainer(); request.CookieContainer.Add(cookies); } return request.GetResponse() as HttpWebResponse; } /// <summary> /// 创建POST方式的HTTP请求 /// </summary> /// <param name="url">请求的URL</param> /// <param name="parameters">随同请求POST的参数名称及参数值字典</param> /// <param name="timeout">请求的超时时间</param> /// <param name="userAgent">请求的客户端浏览器信息,可以为空</param> /// <param name="requestEncoding">发送HTTP请求时所用的编码</param> /// <param name="cookies">随同HTTP请求发送的Cookie信息,如果不需要身份验证可以为空</param> /// <returns></returns> public static HttpWebResponse CreatePostHttpResponse(string url,IDictionary<string,string> parameters,int? timeout, string userAgent,Encoding requestEncoding,CookieCollection cookies) { if (string.IsNullOrEmpty(url)) { throw new ArgumentNullException("url"); } if(requestEncoding==null) { throw new ArgumentNullException("requestEncoding"); } HttpWebRequest request=null; //如果是发送HTTPS请求 if(url.StartsWith("https",StringComparison.OrdinalIgnoreCase)) { ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(CheckValidationResult); request = WebRequest.Create(url) as HttpWebRequest; request.ProtocolVersion=HttpVersion.Version10; } else { request = WebRequest.Create(url) as HttpWebRequest; } request.Method = "POST"; request.ContentType = "application/x-www-form-urlencoded"; if (!string.IsNullOrEmpty(userAgent)) { request.UserAgent = userAgent; } else { request.UserAgent = DefaultUserAgent; } if (timeout.HasValue) { request.Timeout = timeout.Value; } if (cookies != null) { request.CookieContainer = new CookieContainer(); request.CookieContainer.Add(cookies); } //如果需要POST数据 if(!(parameters==null||parameters.Count==0)) { StringBuilder buffer = new StringBuilder(); int i = 0; foreach (string key in parameters.Keys) { if (i > 0) { buffer.AppendFormat("&{0}={1}", key, parameters[key]); } else { buffer.AppendFormat("{0}={1}", key, parameters[key]); } i++; } byte[] data = requestEncoding.GetBytes(buffer.ToString()); using (Stream stream = request.GetRequestStream()) { stream.Write(data, 0, data.Length); } } return request.GetResponse() as HttpWebResponse; } private static bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors) { return true; //总是接受  } } } 

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

用法举例
这个类用起来也很简单:
(1)POST数据到HTTPS站点,用它来登录百度:

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

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

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

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

string loginUrl = "http://home.51cto.com/index.php?s=/Index/doLogin";
string userName = "userName"; string password = "password"; IDictionary<string, string> parameters = new Dictionary<string, string>(); parameters.Add("email", userName); parameters.Add("passwd", password); 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内容的方法(包括服务器使用压缩方式传输的数据),但限于篇幅和其它方面的原因,此处省略掉了。如有机会,在以后的文章中会继续讲述这方面的内容。

C# HttpWebRequest GET HTTP HTTPS 请求相关推荐

  1. 在C#用HttpWebRequest中发送GET/HTTP/HTTPS请求

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

  2. .NET WebApi调用微信接口Https请求工具类

    .NET WebApi调用微信接口Https请求工具类 using System; using System.Collections.Generic; using System.IO; using S ...

  3. Charles抓取https请求

    最近公司将Windows产品的http请求,替换成https请求了,当https请求超过5次失败,就自动切换回http请求.测试时使用Charles抓包测试. 一.http抓包 http抓包比较简单, ...

  4. iOS使用自签名证书实现HTTPS请求

    原文链接:http://www.jianshu.com/p/e6a26ecd84aa 由于苹果规定2017年1月1日以后,所有APP都要使用HTTPS进行网络请求,否则无法上架,因此研究了一下在iOS ...

  5. iOS 用自签名证书实现 HTTPS 请求的原理实例讲解

    在16年的WWDC中,Apple已表示将从2017年1月1日起,所有新提交的App必须强制性应用HTTPS协议来进行网络请求.默认情况下非HTTPS的网络访问是禁止的并且不能再通过简单粗暴的向Info ...

  6. java实现https请求

    参考: https://www.cnblogs.com/chinway/p/5802541.html java 实现https请求 JSSE是一个SSL和TLS的纯Java实现,通过JSSE可以很容易 ...

  7. 【Fiddler学习】Fiddler抓包HTTPS请求和手机抓包

    一.安装Fiddler 百度搜索:Fiddler抓包工具,然后安装即可. 然后打开Fiddler工具,打开浏览器随意输入任何网址,就可以在Fiddler看到抓包信息. 但是:默认情况下,Fiddler ...

  8. iOS 10.3下使用Fiddler抓取HTTPS请求

    最近使用Fiddler抓取手机上的HTTPS请求时,遇到一个问题.设置完之后,访问HTTPS的页面,却得到一个错误 网络出错,轻触屏幕重新加载:-1202 (如下图所示) 我印象中,之前都好好的,怎么 ...

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

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

最新文章

  1. 千金买宝刀 | 斜穿交叉路口对应的新颖的赛道
  2. setup.s 总结——Linux-0.11 剖析笔记(四)
  3. 03_数据的特征抽取,sklearn特征抽取API,字典特征抽取DictVectorizer,文本特征抽取CountVectorizer,TF-IDF(TfidfVectorizer),详细案例
  4. 集合框架之Map LinkedHashMap
  5. vue 一个页面有点请求需要同时发送_前端性能优化,这些你都需要知道
  6. 多模光纤收发器的应用领域及适用领域
  7. 真格量化——做空波动率卖期权策略
  8. java代码创建jar_Java 创建ZIP和JAR文件
  9. Excel表格生成sql语句
  10. 学python买什么书-19年学习Python有什么好的书籍推荐吗?
  11. 【转载】.NET系统学习----Assembly
  12. php模拟表单提交,php用fsockopen()函数实现模拟提交表单。
  13. 太棒了!TCP/IP协议 (图解+秒懂+史上最全)
  14. IPv4(分类编址)
  15. 日期类超详解(c++入门)
  16. php 5.6 语法,在PHP 5.6及以上版本中,还可以使用“...”语法实现可变参数列表。...
  17. linux内存占用过高怎么解决,centos7内存占用过高处理方法
  18. kettle启动 carte服务部署
  19. 关于移动端适配,你必须要知道的
  20. python需要电脑多大内存合适_编程用surface怎么样发(学python要多大内存)

热门文章

  1. 一个程序员的爱情表白书
  2. 算法—快速排序Sqrt (C语言)
  3. python程序生成exe_使用Python程序生成QR代码的Python程序
  4. python string转int_我用Python搞资源 [ 02 ]
  5. clickhouse语句_篇四|ClickHouse的可视化界面与集群状态监控
  6. linux安装mysql和使用c语言操作数据库的方法 c语言连接mysql
  7. C++11新特性之八——函数对象function
  8. 【C language】动态数组的创建和使用
  9. Linux之文件通信
  10. 1052 卖个萌 (20 分)