C# Http请求模拟登录
程序员文章站
2022-05-07 12:08:54
...
工作原理
1.通过chrome或firefox等工具的NetWork面板,跟踪到请求过程中传递的 Request Headers。
2.将Request Headers 附加到请求,DoRequest的headers参数。
3.通过chrome或firefox等工具的NetWork面板,跟踪到请求过程中传递的 Form Data。
4.将Form Data 附加到请求中,DoRequest的content参数。
5.请求成功后,将HttpResponseHeader.SetCookie记录到CookieDic集合。
6.下次请求时,附加上第3步的CookieDic集合,即可模拟登录后操作。
封装代码
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
namespace RC.Software.Travel
{
/// <summary>
/// Http请求封装类,用于模拟登录等操作
/// 工作原理:
/// 1.通过chrome的NetWork面板,跟踪到请求过程中传递的 Request Headers
/// 2.将Request Headers 附加到请求。
/// 3.请求成功后,将HttpResponseHeader.SetCookie记录下来。
/// 4.下次请求时,附加上第3步的cookie,即可模拟登录后操作。
/// </summary>
public class HttpRequestHelper
{
/// <summary>
/// cookie集合,用于模拟登陆
/// </summary>
private static readonly Dictionary<string, Cookie> CookieDic = new Dictionary<string, Cookie>();
/// <summary>
/// Http请求
/// </summary>
/// <param name="url"></param>
/// <param name="method"></param>
/// <param name="headers"></param>
/// <param name="content"></param>
/// <returns></returns>
public static string DoRequest(string url, string method, string headers, string content)
{
var request = (HttpWebRequest)WebRequest.Create(url);
request.Method = method;
if (method.Equals("GET", StringComparison.InvariantCultureIgnoreCase))
{
request.MaximumAutomaticRedirections = 100;
request.AllowAutoRedirect = false;
}
#region 1.设置Http头部
if (!string.IsNullOrWhiteSpace(headers))
{
var hsplit = headers.Split(new[] { "\n" }, StringSplitOptions.RemoveEmptyEntries);
foreach (var item in hsplit)
if (!item.StartsWith(":"))
{
var kv = item.Split(':');
if (kv.Length == 2)
{
var key = kv[0].Trim();
var value = string.Join(":", kv.Skip(1)).Trim();
#region 设置http头
switch (key.ToLower())
{
case "accept":
{
request.Accept = value;
break;
}
case "host":
{
request.Host = value;
break;
}
case "connection":
{
if (value == "keep-alive")
request.KeepAlive = true;
else
request.KeepAlive = false; //just test
break;
}
case "content-type":
{
request.ContentType = value;
break;
}
case "user-agent":
{
request.UserAgent = value;
break;
}
case "referer":
{
request.Referer = value;
break;
}
case "content-length":
{
request.ContentLength = Convert.ToInt64(value);
break;
}
case "expect":
{
request.Expect = value;
break;
}
case "if-modified-since":
{
request.IfModifiedSince = Convert.ToDateTime(value);
break;
}
case "cookie":
{
var cc = new CookieCollection();
var cookieString = value;
if (!string.IsNullOrWhiteSpace(cookieString))
{
var spilit = cookieString.Split(';');
foreach (var ci in spilit)
{
var arr = ci.Split('=');
if (kv.Length == 2)
cc.Add(new Cookie(arr[0].Trim(), arr[1].Trim()));
}
}
}
break;
}
#endregion
}
}
}
#endregion
#region 2.设置cookie
request.Headers[HttpRequestHeader.Cookie] = GetCookieStr();
#endregion
#region 3.发送请求数据
if (!string.IsNullOrWhiteSpace(content))
{
var data = Encoding.UTF8.GetBytes(content);
request.ContentLength = data.Length;
using (var stream = request.GetRequestStream())
{
stream.Write(data, 0, data.Length);
stream.Close();
}
}
#endregion
var response = (HttpWebResponse)request.GetResponse();
#region 4.保存cookie,用于下次请求
var cookies = new CookieCollection();
var s = response.Headers[HttpResponseHeader.SetCookie].Replace("HttpOnly,", "").Replace("httponly,", "");
if (!string.IsNullOrWhiteSpace(s))
{
var spilit = s.Split(';');
foreach (var item in spilit)
{
var kv = item.Split('=');
if (kv.Length == 2)
cookies.Add(new Cookie(kv[0].Trim(), kv[1].Trim()));
}
}
foreach (Cookie c in cookies)
if (CookieDic.ContainsKey(c.Name))
CookieDic[c.Name] = c;
else
CookieDic.Add(c.Name, c);
#endregion
var result = GetResponse(response);
return Unicode2String(result);
}
/// <summary>
/// 将Unicode转换为中文
/// </summary>
/// <param name="source"></param>
/// <returns></returns>
public static string Unicode2String(string source)
{
return new Regex(@"\\u([0-9A-F]{4})", RegexOptions.IgnoreCase).Replace(
source, x => string.Empty + Convert.ToChar(Convert.ToUInt16(x.Result("$1"), 16)));
}
/// <summary>
/// 从HttpWebResponse读取响应文本
/// </summary>
/// <param name="response"></param>
/// <returns></returns>
private static string GetResponse(HttpWebResponse response)
{
var defaultEncode = Encoding.UTF8;
var contentType = response.ContentType;
if (contentType.ToLower().Contains("gb2312"))
defaultEncode = Encoding.GetEncoding("gb2312");
else if (contentType.ToLower().Contains("gbk"))
defaultEncode = Encoding.GetEncoding("gbk");
else if (contentType.ToLower().Contains("zh-cn")) defaultEncode = Encoding.GetEncoding("zh-cn");
string responseBody;
if (response.ContentEncoding.ToLower().Contains("gzip"))
using (var stream = new GZipStream(response.GetResponseStream(), CompressionMode.Decompress))
{
using (var reader = new StreamReader(stream))
{
responseBody = reader.ReadToEnd();
}
}
else if (response.ContentEncoding.ToLower().Contains("deflate"))
using (var stream = new DeflateStream(response.GetResponseStream(), CompressionMode.Decompress))
{
using (var reader = new StreamReader(stream, defaultEncode))
{
responseBody = reader.ReadToEnd();
}
}
else
using (var stream = response.GetResponseStream())
{
using (var reader = new StreamReader(stream, defaultEncode))
{
responseBody = reader.ReadToEnd();
}
}
return responseBody;
}
private static string GetCookieStr()
{
var sb = new StringBuilder();
foreach (var item in CookieDic)
if (!item.Value.Expired)
{
if (sb.Length == 0)
sb.Append(item.Key).Append("=").Append(item.Value.Value);
else
sb.Append("; ").Append(item.Key).Append(" = ").Append(item.Value.Value);
}
return sb.ToString();
}
}
}
调用示例代码:
var userName = txtUserName.Text.Trim();
var pwd = txtPwd.Text.Trim();
var res = HttpRequestHelper.DoRequest(_loginUrl, "Post", txtHeaders.Text.Trim(), "passport=" + userName + "&password=" + pwd);
txtResult.Text = res;
上一篇: 丑数问题
下一篇: RabbitMQ基础个人总结篇