c# https请求
遇到Https网站,c# http请求的时候,总是报SSL连接错误。后来经搜索,发现有解决方案:
.net 2.0 需要引入一个第三方组件:BouncyCastle.dll,这是我写的一个例子:
public static string RequestWebServerByTCP(Uri uri, string method, NameValueCollection parameter, string cookie, Encoding encoding){try{StringBuilder RequestHeaders = new StringBuilder();RequestHeaders.Append(method + " " + uri.PathAndQuery + " HTTP/1.1\r\n");method = method.ToUpper();if (method == POSTMETHOD)RequestHeaders.Append("Content-Type:application/x-www-form-urlencoded\r\n");RequestHeaders.Append("User-Agent:Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11\r\n");RequestHeaders.Append("Cookie:" + cookie + "\r\n");RequestHeaders.Append("Accept:*/*\r\n");RequestHeaders.Append("Host:" + uri.Host + "\r\n");byte[] postdata = null;StringBuilder sb = new StringBuilder();if (method == GETMETHOD){uri = GetMethodQueryString(uri, parameter, encoding);}else if (method == POSTMETHOD){if (parameter != null){foreach (string key in parameter){sb.Append(string.Format(FORMATSTR1, System.Web.HttpUtility.UrlEncode(key, encoding), System.Web.HttpUtility.UrlEncode(parameter[key], encoding)));}}if (sb.Length != 0){sb = sb.Remove(sb.Length - 1, 1);}postdata = encoding.GetBytes(sb.ToString());RequestHeaders.Append("Content-Length:" + postdata.Length + "\r\n");}RequestHeaders.Append("Connection:close\r\n\r\n");byte[] req = Encoding.UTF8.GetBytes(RequestHeaders.ToString() + sb.ToString());int port = 443;MyTlsClient client = new MyTlsClient();var protocol = OpenTlsConnection(uri.Host, port, client);Stream tlsStream = protocol.Stream;tlsStream.Write(req, 0, req.Length);tlsStream.Flush();StreamReader reader = new StreamReader(tlsStream);String line;StringBuilder html = new StringBuilder();string firstLine = "";int i = 0;while ((line = reader.ReadLine()) != null){if (i == 0){firstLine = line;i++;}html.AppendLine(line);if (line.Contains("</html>")){break;}}protocol.Close();string httpstatusCode = "";string[] httpstatus = firstLine.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries);if (httpstatus.Length > 2){httpstatusCode = httpstatus[1];}else{//请求无效httpstatusCode = "400";}return html.ToString();}catch{return "";}}
请求到的html,为什么需要一行一行读呢?我在调试的时候发现有个bug,如果一次性读取的时候,它停不下来,最终报错,所以我做了一个读到html末尾的判断。
继承了提供的默认类:
class MyTlsClient : DefaultTlsClient{public override TlsAuthentication GetAuthentication(){return new MyTlsAuthentication();}}// Need class to handle certificate auth class MyTlsAuthentication : TlsAuthentication{public TlsCredentials GetClientCredentials(CertificateRequest certificateRequest){// return client certificate return null;}public void NotifyServerCertificate(Certificate serverCertificate){// validate server certificate }}
internal static TlsClientProtocol OpenTlsConnection(string hostname, int port, TlsClient client){TcpClient tcp = new TcpClient(hostname, port);TlsClientProtocol protocol = new TlsClientProtocol(tcp.GetStream(), secureRandom);protocol.Connect(client);return protocol;}
拼接url参数的方法:
private static Uri GetMethodQueryString(Uri uri, NameValueCollection parameter, Encoding encoding){List<KeyValuePair<string, string>> parameter1 = new List<KeyValuePair<string, string>>();foreach (string key in parameter){parameter1.Add(new KeyValuePair<string, string>(key, parameter[key]));}return GetMethodQueryString(uri, parameter1, encoding);}private static Uri GetMethodQueryString(Uri uri, List<KeyValuePair<string, string>> parameter, Encoding encoding){string format = string.Empty;UriBuilder uribuilfer = new UriBuilder(uri);string QueryString = string.Empty;if (string.IsNullOrEmpty(uribuilfer.Query)){format = FORMATSTR1;}else{format = FORMATSTR2;}QueryString = uribuilfer.Query;if (parameter != null){foreach (KeyValuePair<string, string> item in parameter){QueryString += string.Format(format, System.Web.HttpUtility.UrlEncode(item.Key, encoding), System.Web.HttpUtility.UrlEncode(item.Value, encoding));}}QueryString = QueryString.TrimEnd(new char[] { '&' });QueryString = QueryString.TrimStart(new char[] { '?' });uribuilfer.Query = QueryString;uri = uribuilfer.Uri;return uri;}
注意:List<KeyValuePair<string, string>>和NameValueCollection类型的参数有什么区别呢?它们都包含相同的key,只不过存储的时候,NameValueCollection会把含有相同Key的值用逗号隔开,存在一起。这样请求有可能会失败,拿不到数据。本人因此问题,折腾了很久,用python实现了请求,后来在.net core中实现了一遍,最后终于低下了高傲的头颅,才看到传参时候,有点问题。
.net 4.0中,只需要添加一句话:ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072;
.net 4.5中,什么都不用管。
2.0中连TCP都用上了,不过我们看到了http请求的本质,把一段具有格式的请求头+请求数据转为二进制发送到主机的某个端口,返回流,通过读取流,就可以拿到结果。
说到这,我们来看看Request消息格式:
GET https://www.baidu.com/ HTTP/1.1 Accept: text/html, application/xhtml+xml, */* Accept-Language: zh-CN User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko Accept-Encoding: gzip, deflate Connection: Keep-Alive Host: www.baidu.com Cookie: BAIDUID=C1EFC3A3466AAAEBE74C6F6E7F413FA8:FG=1; BIDUPSID=C1EFC3A3466AAAEBE74C6F6E7F413FA8; PSTM=1525339270; BD_LAST_QID=12260391193367555241
1、请求行,包含请求的方法,url,http协议版本
2、请求头,接收的格式,浏览器代理,cookie等等
3、空行
4、请求体,传递数据
Response格式:
HTTP/1.1 200 OK Bdpagetype: 1 Bdqid: 0x9a1ff959000016d0 Cache-Control: private Connection: Keep-Alive Content-Encoding: gzip Content-Type: text/html; charset=utf-8 Cxy_all: baidu+77e5655ffd82ce31adf5edff251fc585 Date: Thu, 03 May 2018 09:21:10 GMT Expires: Thu, 03 May 2018 09:21:03 GMT Server: BWS/1.1 Set-Cookie: BDSVRTM=0; path=/ Set-Cookie: BD_HOME=0; path=/ Set-Cookie: H_PS_PSSID=1428_21080_20719; path=/; domain=.baidu.com Strict-Transport-Security: max-age=172800 Vary: Accept-Encoding X-Powered-By: HPHP X-Ua-Compatible: IE=Edge,chrome=1 Transfer-Encoding: chunked html
1、状态行
2、消息报头,content-type,Date,Set-Cookie
3、空行
4、正文
转载于:https://www.cnblogs.com/wangqiang3311/p/8986603.html
c# https请求相关推荐
- Charles抓取https请求
最近公司将Windows产品的http请求,替换成https请求了,当https请求超过5次失败,就自动切换回http请求.测试时使用Charles抓包测试. 一.http抓包 http抓包比较简单, ...
- iOS使用自签名证书实现HTTPS请求
原文链接:http://www.jianshu.com/p/e6a26ecd84aa 由于苹果规定2017年1月1日以后,所有APP都要使用HTTPS进行网络请求,否则无法上架,因此研究了一下在iOS ...
- iOS 用自签名证书实现 HTTPS 请求的原理实例讲解
在16年的WWDC中,Apple已表示将从2017年1月1日起,所有新提交的App必须强制性应用HTTPS协议来进行网络请求.默认情况下非HTTPS的网络访问是禁止的并且不能再通过简单粗暴的向Info ...
- java实现https请求
参考: https://www.cnblogs.com/chinway/p/5802541.html java 实现https请求 JSSE是一个SSL和TLS的纯Java实现,通过JSSE可以很容易 ...
- 【Fiddler学习】Fiddler抓包HTTPS请求和手机抓包
一.安装Fiddler 百度搜索:Fiddler抓包工具,然后安装即可. 然后打开Fiddler工具,打开浏览器随意输入任何网址,就可以在Fiddler看到抓包信息. 但是:默认情况下,Fiddler ...
- 在C#用HttpWebRequest中发送GET/HTTP/HTTPS请求
这个需求来自于我最近练手的一个项目,在项目中我需要将一些自己发表的和收藏整理的网文集中到一个地方存放,如果全部采用手工操作工作量大而且繁琐,因此周公决定利用C#来实现.在很多地方都需要验证用户身份才可 ...
- iOS 10.3下使用Fiddler抓取HTTPS请求
最近使用Fiddler抓取手机上的HTTPS请求时,遇到一个问题.设置完之后,访问HTTPS的页面,却得到一个错误 网络出错,轻触屏幕重新加载:-1202 (如下图所示) 我印象中,之前都好好的,怎么 ...
- httpsrequest java_java 发送http和https请求的实例
HTTP请求: 如果需要Json格式的自己转下,度娘上N种姿势- //处理http请求 requestUrl为请求地址 requestMethod请求方式,值为"GET"或&quo ...
- Fiddler抓包1-抓firefox上https请求
前言 fiddler是一个很好的抓包工具,默认是抓http请求的,对于pc上的https请求,会提示网页不安全,这时候需要在浏览器上安装证书. 一.网页不安全 1.用fiddler抓包时候,打开百度网 ...
- Android 7.0解决抓取不到https请求的问题
Android 7.0解决抓取不到https请求的问题 参考文章: (1)Android 7.0解决抓取不到https请求的问题 (2)https://www.cnblogs.com/meitian/ ...
最新文章
- 小米 Play 发布:CPU+GPU 双 Turbo,每个月送 10 GB 流量
- Elastic-Job中的SimpleJob
- bootstraptable获得所有行_2020广汽本田安全中国行·首届道路安全创新大赛成功举办...
- .Net开源的跨平台爬虫框架 DotnetSpider
- 中科大 计算机网络12 Web和HTTP
- 计算机网络 第五章 课后题答案
- 时间管理——34枚金币
- 安全面试之WEB安全(一)
- CF838D Airplane Arrangements
- 2021肇庆各中学高考成绩查询入口,2021高考即将来袭!肇庆各学校的同学们准备好了吗?...
- Android并发之Executor(线程池)家族(二)之AtomicInteger
- 巡查使:智能巡检领域“引航者”
- 堡垒机定义、由来以及价值简单说明
- 谏言工信部:网站备案系统miibeian.gov.cn实在难用!
- 暗影精灵 官方恢复出厂系统镜像HP Cloud Recovery Tool
- 面对HP MSA存储中硬盘掉线的情况,学会这种解决方式至关紧要
- Python 桌面整理小工具程序
- vis教程(加动画、加点击事件)
- python colors属于哪个包,Colour首页、文档和下载 - Python 颜色科学软件包
- 记录解决windows下安装cocoapi的几种方案