C# 实现模拟登录功能,实现公共类分享。
前言
最近在研究模拟登录的各种方法, 主要想要实现的两个功能是:
1.点击按钮可以直接跳转并登录到某一个系统中。
2.抓取某一个系统中某一个页面中的特定数据。
为此在网上查了许多的资料,首先了解到自身对http协议基础知识的欠缺,初步了解后,明白想要实现模拟登录首先要学会抓包这一项基本的技能,关于抓包这里就不详细介绍了,向大家推荐一款软件fiddler,一款不错的抓包软件。
首先客户端向服务端请求无非两种类型get或post,所以我们要了解在登录某一个系统时post的地址,以及需要post的参数。这些都需要通过抓包来获取。
一、简单的表单提交
第一种功能跳转就是简单的表单的提交,所有系统的登录都是表单的post提交,所以只需要在html中模拟写出该系统的表单需要提交的参数并赋值,提交表单即可跳转。
/// <summary>
///返回html表单
///action post地址,postDict键值对
/// <summary>
public string getPostFormHtml(HJFormModel model)
{
string action = model.action;
Dictionary<string, string> postDict = model.postDict;
StringBuilder sb = new StringBuilder();
sb.Append("<form method=\"post\" id=\"myHttpForm\" action=\"" + action + "\">");
sb.Append(" <div>");
sb.Append(" <br />");
foreach (var dic in postDict)
{
sb.Append(" <input type=\"hidden\" name=\"" + dic.Key + "\" value=\"" + dic.Value + "\" />");
}
sb.Append(" <input type=\"submit\" value=\"登录\" />");
sb.Append(" </div>");
sb.Append(" </form>");
return sb.ToString();
}
/// <summary>
/// Form表单生成请求参考类
/// </summary>
public class HJFormModel
{ /// <summary>
/// 表单提交地址
/// </summary>
public string action { get; set; }
/// <summary>
/// 需要提交的数据参数
/// </summary>
public Dictionary<string, string> postDict { get; set; }
}
上面是代码下面是请求类,就是从后台返回html,生成一个表单,提交即可,其中postDict 指需要提交的参数这里由键值对来赋值,如遇到需要输入验证码的登录那么就需要增加一条验证码连接的图片,人工识别填写(目前没有想到更好的方法)。
二、模拟登录抓取页面数据
第二种功能抓取页面的特定数据,其实就是获取某一页面所以的html,顺序一样首先要登录到系统中,下面附上公共类的代码。
/// <summary>
///根据参数,返回指定内容
/// <summary>
public HJHttpResult GetHtml(HJHttpItem Item)
{
HJHttpResult res = new HJHttpResult();
try
{
string htmldate;
string html;
CookieCollection cook = new CookieCollection();
cook = getCook(Item.GetCookieUrl, Item.Domain, Item.CookName);
if (!string.IsNullOrWhiteSpace(Item.postStingData))
{
postCookLogin(Item.PostUrl, cook, Item.postStingData);
}
else
{
postCookLogin(Item.PostUrl, cook, Item.postKeyData);
}
html = getAllHtml(Item.GetHtmlUrl, cook);
if (!string.IsNullOrWhiteSpace(html))
{
htmldate = getCutOutHtml(Item.beginString, Item.finishString, html);
}
else
{
htmldate = "获取失败";
}
res.html = htmldate;
res.CookieCoken = cook;
return res;
}
catch (Exception ex)
{
res.html = "获取失败" + ex.Message;
return res;
}
} /// <summary>
/// 已登录成功根据Cookie查询其他特定HTML
/// <summary>
public string GetUrlHtml(string beginString, string finishString, string Url, CookieCollection curCookies)
{
string html;
try
{
string AllHtml = getAllHtml(Url, curCookies);
html = getCutOutHtml(beginString, finishString, AllHtml);
return html;
}
catch (Exception ex)
{
html = "获取失败,请重新Post登录" + ex.Message;
return html;
}
}
/// <summary>
///截取html中特定的数据,beginString起始,finishString结束,html
/// <summary>
public string getCutOutHtml(string beginString, string finishString, string html)
{
int a = beginString.Length;
int i = html.IndexOf(beginString) + a;
int j = html.IndexOf(finishString);
return html.Substring(i, j - i);
} /// <summary>
///获取cookie
///url 获取地址,Domain Cook中的Domain,有哪些CookName
/// <summary>
public CookieCollection getCook(string Url, string Domain, string[] CookName)
{
CookieCollection curCookies = new CookieCollection(); HttpWebRequest reqget = (HttpWebRequest)WebRequest.Create(Url); reqget.CookieContainer = new CookieContainer();
reqget.CookieContainer.Add(curCookies); reqget.Method = "GET";
HttpWebResponse respget = (HttpWebResponse)reqget.GetResponse(); foreach (Cookie ck in respget.Cookies)
{
for (int i = ; i < CookName.Length; i++)
{
if (ck.Name == CookName[i])
{
Cookie cookget = new Cookie();
cookget.Value = ck.Value;
cookget.Name = ck.Name;
cookget.Domain = Domain;
curCookies.Add(cookget);
}
}
}
string DefaultUserAgent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)";
HttpWebRequest request = WebRequest.Create(Url) as HttpWebRequest;
request.Method = "GET";
request.UserAgent = DefaultUserAgent; request.CookieContainer = new CookieContainer();
request.CookieContainer.Add(curCookies); return curCookies;
} /// <summary>
///post登录
///Url post 地址 ,postdata POST数据(字符串),curCookies COOKIE
/// <summary>
public void postCookLogin(string Url, CookieCollection curCookies, string postData)
{
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(Url);
//add cookie
req.CookieContainer = new CookieContainer();
req.CookieContainer.Add(curCookies);
//set to POST
req.Method = "POST";
req.ContentType = "application/x-www-form-urlencoded";
//prepare post data
//string postDataStr = quoteParas(postDict);
byte[] postBytes = Encoding.UTF8.GetBytes(postData);
req.ContentLength = postBytes.Length; //send post data
Stream postDataStream = req.GetRequestStream();
postDataStream.Write(postBytes, , postBytes.Length);
postDataStream.Close(); //got response
HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
string url = resp.ResponseUri.ToString(); //got returned html
StreamReader sr = new StreamReader(resp.GetResponseStream());
}
/// <summary>
///Url post 地址 ,postdata POST数据(键值对),curCookies COOKIE
/// <summary>
public void postCookLogin(string Url, CookieCollection curCookies, Dictionary<string, string> postData)
{
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(Url);
//add cookie
req.CookieContainer = new CookieContainer();
req.CookieContainer.Add(curCookies);
//set to POST
req.Method = "POST";
req.ContentType = "application/x-www-form-urlencoded";
//prepare post data
string postDataStr = quoteParas(postData);
byte[] postBytes = Encoding.UTF8.GetBytes(postDataStr);
req.ContentLength = postBytes.Length; //send post data
Stream postDataStream = req.GetRequestStream();
postDataStream.Write(postBytes, , postBytes.Length);
postDataStream.Close(); //got response
HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
string url = resp.ResponseUri.ToString(); //got returned html
StreamReader sr = new StreamReader(resp.GetResponseStream());
} /// <summary>
///获取html页面
///cookCon 已登录成功的cook,Url 地址
/// <summary>
public string getAllHtml(string Url, CookieCollection curCookies)
{
CookieContainer cookCon = new CookieContainer();
cookCon.Add(curCookies);
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(Url);
//属性配置
webRequest.AllowWriteStreamBuffering = true;
webRequest.Credentials = System.Net.CredentialCache.DefaultCredentials;
webRequest.MaximumResponseHeadersLength = -;
//webRequest.Accept = "image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*";
webRequest.UserAgent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Maxthon; .NET CLR 1.1.4322)";
webRequest.ContentType = "application/x-www-form-urlencoded";
webRequest.Method = "GET";
webRequest.Headers.Add("Accept-Language", "zh-cn");
webRequest.Headers.Add("Accept-Encoding", "gzip,deflate");
webRequest.KeepAlive = true;
webRequest.CookieContainer = cookCon;
try
{
//获取服务器返回的资源
using (HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse())
{
using (Stream sream = webResponse.GetResponseStream())
{
StreamReader streamReader = new StreamReader(sream);
string str = streamReader.ReadToEnd();
return str;
}
}
}
catch (WebException ex)
{
return "错误" + ex.Message;
}
}
/// <summary>
///get方式获取验证码
///Url验证码的地址,COOKie cookCon,savePath保存地址
/// <summary>
public bool boolDowloadCheckImg(string Url, CookieContainer cookCon, string savePath)
{
bool bol = true;
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(Url);
//属性配置
webRequest.AllowWriteStreamBuffering = true;
webRequest.Credentials = System.Net.CredentialCache.DefaultCredentials;
webRequest.MaximumResponseHeadersLength = -;
//webRequest.Accept = "image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*";
webRequest.UserAgent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Maxthon; .NET CLR 1.1.4322)";
webRequest.ContentType = "application/x-www-form-urlencoded";
webRequest.Method = "GET";
webRequest.Headers.Add("Accept-Language", "zh-cn");
webRequest.Headers.Add("Accept-Encoding", "gzip,deflate");
webRequest.KeepAlive = true;
webRequest.CookieContainer = cookCon;
try
{
//获取服务器返回的资源
using (HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse())
{
using (Stream sream = webResponse.GetResponseStream())
{
List<byte> list = new List<byte>();
while (true)
{
int data = sream.ReadByte();
if (data == -)
break;
list.Add((byte)data);
}
File.WriteAllBytes(savePath, list.ToArray());
}
}
}
catch (WebException ex)
{
bol = false;
}
catch (Exception ex)
{
bol = false;
}
return bol;
} //quote the input dict values
//note: the return result for first para no '&'
/// <summary>
///键值对与字符流转换
/// <summary>
public string quoteParas(Dictionary<string, string> paras)
{
string quotedParas = "";
bool isFirst = true;
string val = "";
foreach (string para in paras.Keys)
{
if (paras.TryGetValue(para, out val))
{
if (isFirst)
{
isFirst = false;
quotedParas += para + "=" + HttpUtility.UrlPathEncode(val);
}
else
{
quotedParas += "&" + para + "=" + HttpUtility.UrlPathEncode(val);
}
}
else
{
break;
}
} return quotedParas;
} }
/// <summary>
/// Http请求参考类
/// </summary>
public class HJHttpItem
{
/// <summary>
/// 获得Cookie的URL
/// </summary>
public string GetCookieUrl { get; set; }
/// <summary>
/// Cookie的Domain
/// </summary>
public string Domain { get; set; }
/// <summary>
/// 截取Html的起始位置
/// </summary>
public string beginString { get; set; }
/// <summary>
/// 截取Html的终止位置
/// </summary>
public string finishString { get; set; }
/// <summary>
/// Cookie的Name集合{"",""}
/// </summary>
public string[] CookName { get; set; }
/// <summary>
/// post的数据字符串格式 注:与postKeyData必须有一个不是为空的
/// </summary>
public string postStingData { get; set; }
/// <summary>
/// post的数据键值对格式 注:与postStingData必须有一个不是为空的
/// </summary>
public Dictionary<string, string> postKeyData { get; set; }
/// <summary>
/// post的地址
/// </summary>
public string PostUrl { get; set; }
/// <summary>
/// 获取Html的地址
/// </summary>
public string GetHtmlUrl { get; set; }
}
/// <summary>
/// Http返回参数类
/// </summary>
public class HJHttpResult
{ /// <summary>
/// 返回的Html数据
/// </summary>
public string html { get; set; }
/// <summary>
/// 返回的Cookie数据
/// </summary>
public CookieCollection CookieCoken { get; set; }
}
大致原理为,首先获取相应登录系统的Cookie,这里我们要理解一下Cookie中SessionID的用处,SessionID由服务端向客户端发起,每次打开浏览器会更新SessionID,SessionID的目的是为了存贮post提交后登录状态的信息,如登录的用户,这个由系统而定,获得Cookie后利用这个Cookie和postdata向post地址提交,这时如果登录成功SessionID就记录下该账号的登录状态,此时利用SessionID访问该域下的其他页面就可以了,获取下来html截取下来想要的数据,同样有需要验证码的get方法获取验证码,人工识别输入post登录。
三、小结
最近在这方面做了一些小研究,遇到的问题还有很多,比如如何从后台登录成功后可以跳转到浏览器中并保持登录状态,而且我做测试的用的都是一些较为简单的系统,需要的参数并不复杂,如果哪位大神对这方面有着较深的研究,或者有这方面比较完善的系统可以分享,欢迎指出思路或其他有错误的地方,感激不尽。
C# 实现模拟登录功能,实现公共类分享。的更多相关文章
- PHP简单模拟登录功能实例分享
1.curl实现模拟登录的代码,(只是实现服务器与服务器建立会话,其实并没有在客户端与服务器之间建立会话) <?php $cookie_jar = tempnam('./tmp','cookie ...
- 测试开发Python培训:模拟登录新浪微博-技术篇
测试开发Python培训:模拟登录新浪微博-技术篇 一般一个初学者项目的起点就是登陆功能的自动化,而面临的项目不同实现的技术难度是不一样的,poptest在做测试开发培训中更加关注技术难点,掌握技 ...
- HttpWebRequest 模拟登录响应点击事件(分享自己用的HttpHelper类)
平时也经常采集网站数据,也做模拟登录,但一般都是html控件POST到页面登录:还没有遇到用户服务器控件button按钮点击事件登录的,今天像往常一样POST传递参数,但怎么都能登录不了:最后发现还有 ...
- 模拟登录神器之PHP基于cURL实现自动模拟登录类
一.构思 从Firefox浏览器拷贝cURL命令(初始页.提交.提交后) 自动分析curl形成模拟登录代码 默认参数:ssl/302/gzip 二.实现 接口 (一)根据curl信息执行并解析结果 p ...
- Android+struts2+json方式模拟手机登录功能
涉及到的知识点: 1.Struts2框架的搭建(包括Struts2的jSON插件) 2.Android前台访问Web采用HttpClient方式. 3.Android采用JSON的解析. 服务端主要包 ...
- 用java集合模拟登录和注册功能
package com.linkage.login; import java.util.HashMap;import java.util.Iterator;import java.util.Map;i ...
- 用java数组模拟登录和注册功能
package com.linkage.login; import java.util.Scanner; public class user { // 存储用户名和密码 public static S ...
- HttpClient + Jsoup模拟登录教务处并获取课表
1.概述 最近想做一个校园助手类的APP,由于第一次做,所以打算先把每个功能单独实现,防止乱了阵脚.利用教务处登录获取课表和成绩等是一个基本功能,所以以获取课表为例实现了这个功能.完整代码点这里,尝试 ...
- javamail模拟邮箱功能发送电子邮件-中级实战篇【新增附件发送方法】(javamail API电子邮件实例)
引言: JavaMail jar包下载地址:http://java.sun.com/products/javamail/downloads/index.html 此篇是紧随上篇文章而封装出来的,阅读本 ...
随机推荐
- 发博客用的一些HTML
这个世界,在发生什么? 移动光标 <p style="background: #999999; padding: 5px; font-size: 22px;">< ...
- python之总体理解
作为脚本,python具备了弱类型语言的灵活性,便捷性.这在日常的开发使用中能够大幅度的减轻开发人员的编码负担,开发者也能够将精力集中在程序的逻辑管理和总体构架设计上.一般而言,随着经验的积累,开发人 ...
- [js] 小谈 export (没总结完)
作用 导出变量/类 等等 用法 index.js 文件 export default name 仅导出一个变量 import name from './index.js' index.js 文件 ex ...
- 【Mysql】MySQL与Oracle的大小写问题
转载来源:http://aofengblog.blog.163.com/blog/static/63170212010101065030136/ MySQL与Oracle在大小写处理上的区别: 1MY ...
- 关于SQL语句条件值写中文查不到的问题
在使用jdbc链接MySQL执行SQL语句的时候,sql语句中的where条件,参数值带中文,则查询不到结果,而where条件,参数值都为数字或字母时可以正常查询, 原因是mysql的characte ...
- Spring整合CXF webservice restful 实例
webservice restful接口跟soap协议的接口实现大同小异,只是在提供服务的类/接口的注解上存在差异,具体看下面的代码,然后自己对比下就可以了. 用到的基础类 User.java @Xm ...
- selenium+python开发环境的搭建
web 调试工具介绍和开发环境搭建 python与selenium开发环境搭建: 一.下载python软件:https://www.python.org/ 下载完后,进行安装,安装成功后,打开IDLE ...
- vue模板的几种写法及变化
第一种: 2+版本支持,1+版本支持 <script> <template id="aaa"> <h1>我是组件2</h1> < ...
- setTimeout 与 Event Loop 浅析
先从一个小题目开始: 以下代码的输出结果是? function test1 () { console.log(1) }; setTimeout(test1, 1000); // T1-1setTime ...
- 初探IAT
---恢复内容开始--- IAT(Import Address Table:输入函数地址表) [IAT作用是什么:] 一个API函数,比如MessageBoxA,我们是如何调用它的呢, 在这里我们可以 ...