c# 执行js的方法
http://www.cnblogs.com/wuhuacong/archive/2010/11/08/1871866.html
为了有效阻止恶意用户的攻击,一般登录都会采用验证码方式方式处理登录,类似QQ的很多产品的验证码处理,但在一些OA系统中,系统通过非对称加密方式来处理登录的密码信息,登录页面每次提供对密码进行加密的公钥是不同的,因此如果要模拟登录,就需要先获取公钥,然后根据公钥把输入的密码加密,然后通过POST提交给服务器进行验证登录。由于公钥是页面刷新变化的,而加密是通过Javascript脚本进行加密,如下面的登录页面源码所示。
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<link rel="stylesheet" type="text/css" href="/templates/2008/index.css">
<link rel="shortcut icon" href="/images/tongda.ico">
<script src="/inc/js/rsa/jsbn.js"></script><script src="/inc/js/rsa/prng4.js"></script><script src="/inc/js/rsa/rng.js"></script><script src="/inc/js/rsa/rsa.js"></script>
<script type="text/javascript">
function CheckForm()
{
var rsa = new RSAKey();
rsa.setPublic("97e256ec6147b7aadc46a353b5c5d707a895b402d114290c0c24a28919507569", "10001");
try{
document.form1.PASSWORD.value = rsa.encrypt(document.form1.PASSWORD.value);
}
catch(ex){
return false;
}
return true;
}
</script>
</head>
<body onload="javascript:document.form1.PASSWORD.focus();">
<br>
<br>
<br>
<br>
<div align="center">
<form name="form1" method="post" action="logincheck.php" autocomplete="off" onsubmit="return CheckForm();">
<table cellspacing="0" cellpadding="0" align="center">
<tr class="img_field">
<td align="center"><img src="/attachment/2090997160/index_1.jpg" width="651" height="241"></td>
</tr>
<tr height="37" class="login_field">
<td align="center">
<b>用户名</b> <input type="text" class="text" name="UNAME" size="15" onmouseover="this.focus()" onfocus="this.select()" value="">
<b>密码</b> <input type="password" class="text" name="PASSWORD" onmouseover="this.focus()" onfocus="this.select()" size="15" value="">
<select name="UI">
<option value="0">标准界面</option></select>
<input type="submit" name="submit" class="submit" value="登 录">
</td>
</tr>
</table>
<br>
</form>
为了模拟登录,我们需要先获取页面的公钥信息,然后通过在C#中运行Javascript脚本,传递公钥和明文密码,然后获取脚本加密的结果,再提交给服务器处理。
如下面代码所示,获取公钥就是分析HTML源码,通过正则表达式匹配即可获取到,相对比较简单,但是要获取Javascript脚本的运行结果,就需要花点功夫了。
///inc/js/rsa/jsbn.js /inc/js/rsa/prng4.js /inc/js/rsa/rng.js /inc/js/rsa/rsa.js
string scriptUrl = "http://www.abc.cn:8080/inc/js/rsa/jsbn.js";
string scriptUrl2 = "http://www.abc.cn:8080/inc/js/rsa/prng4.js";
string scriptUrl3 = "http://www.abc.cn:8080/inc/js/rsa/rng.js";
string scriptUrl4 = "http://www.abc.cn:8080/inc/js/rsa/rsa.js";
string referen = "http://www.abc.cn:8080";
HttpHelper helper = new HttpHelper();
helper.Encoding = Encoding.Default; string mainContent = helper.GetHtml(referen, cookie, referen); string regex = "rsa.setPublic\\(\"(?<publicKey>.*?)\",\\s*\"(?<encrypt>.*?)\"\\);";
Regex re = new Regex(regex, RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.IgnorePatternWhitespace);
Match mc = re.Match(mainContent);
if (mc.Success)
{
string publicKey = mc.Groups["publicKey"].Value;
string encrypt = mc.Groups["encrypt"].Value;
string pass = config.AppConfigGet("ContactPassword"); string source = "";//"var appName = \"Microsoft Internet Explorer\"; " + Environment.NewLine;
source += helper.GetHtml(scriptUrl);
source += helper.GetHtml(scriptUrl2);
source += helper.GetHtml(scriptUrl3);
source += helper.GetHtml(scriptUrl4);
//source = source.Replace("navigator.", "");
source = getJS(source); encryptPass = scriptEngine.Eval("getRSAKey()",
source +
"\r\nfunction getRSAKey(){\r\nvar RSA = new RSAKey();\r\nRSA.setPublic(\"" +
publicKey + "\",\"" + encrypt + "\");\r\nvar Res = RSA.encrypt('" + pass + "');\r\nreturn Res;\r\n}").ToString(); }
#endregion
上面的运行Javascript脚本,需要先把用到的脚本全部下载,把内容组合起来,然后添加一个虚拟的函数,运行得到返回结果接口,虚拟的函数一定要写正确,否则出来很多错误,得不到结果。
上面的代码有source = getJS(source);这一句,是为了避免脚本调用navigator.appName来处理浏览器类型和版本的判断,有两种方式可以跳过这个处理,一个增加一个appName的变量,如var appName =**这样,然后统一替换navigator. 的字符,使得脚本判别浏览器代码失效;二是通过正则表达式替换掉响应的判断代码即可
private string getJS(string strJS)
{
if (!Regex.IsMatch(strJS, @"if\(j_lm \&\& \(navigator.appName == ""Microsoft Internet Explorer""\)\) {.+?dbits = 28;.+?}", RegexOptions.Singleline) ||
!Regex.IsMatch(strJS, @"if\(navigator.appName == ""Netscape"" && navigator.appVersion < ""5"" && window.crypto\) {.+?}", RegexOptions.Singleline))
{
return string.Empty;
} strJS = Regex.Replace(strJS,
@"if\(j_lm \&\& \(navigator.appName == ""Microsoft Internet Explorer""\)\) {.+?dbits = 28;.+?}",
"BigInteger.prototype.am = am2;\r\ndbits = 30\r\n", RegexOptions.Singleline);
strJS = Regex.Replace(strJS,
@"if\(navigator.appName == ""Netscape"" && navigator.appVersion < ""5"" && window.crypto\) {.+?}",
string.Empty, RegexOptions.Singleline);
return strJS;
}
得到处理过的密码密文 ,一般通过POST方式提交登录页面,即可完成系统的登录了,然后继续可以通过HttpRequest方式获取系统各种页面的信息了(如联系人等),如下面所示。
string referen = "http://www.abc.cn:8080/";
string loginUrl = "http://www.abc.cn:8080/logincheck.php";
string login = "test";
string loginPostData = string.Format("UNAME={1}&PASSWORD={0}&UI=0&submit={2}", encryptPass, login, "%B5%C7+%C2%BC"); string conctactUrl = "http://www.abc.cn:8080/general/ipanel/user/search.php";
string itemRegex = "<tr\\s*class=\"TableLine\\d\">\\s*(.*?)\\s*</tr>";
string memberRegex = "<td.*?>\\s*(.*?)\\s*</td>"; List<ContactInfo> contactList = new List<ContactInfo>();
HttpHelper helper = new HttpHelper();
helper.Encoding = Encoding.Default; string result = helper.GetHtml(loginUrl, cookie, loginPostData, true, "", loginUrl);
最后程序处理登录后,自动获取联系人的界面效果如下所示:
除了上面的操作方式,还有一种途径是通过WebBrowser控件实现数据的自动提交,WebBrowser控件处理脚本的运行更加方便,但缺点是这个控件相对较慢,首先我介绍一下这种方式,在按钮触发中调用控件的Navigate函数,打开相应的登录链接地址。
webBrowser1.Navigate("http://www.abc.cn:8080");
接着在浏览器控件的页面完成函数处理中对数据进行处理,处理的思路就是调用脚本对输入的内容进行加密,然后再触发提交按钮即可完成页面的登录,记录登录的信息,然后再去获取相关的页面内容信息,不过这种控件处理相对没那么大的弹性处理,不过可以作为一些功能的补充使用。
private int numtries = 0;
private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
if (webBrowser1.Document.GetElementById("UNAME") != null)
{
webBrowser1.Document.GetElementById("UNAME").SetAttribute("value", "陈建才");
webBrowser1.Document.GetElementById("PASSWORD").SetAttribute("value", "voowoo770916"); if (numtries < 2)
{
IHTMLWindow2 login = (mshtml.IHTMLWindow2)webBrowser1.Document.Window.DomWindow;
//login.execScript("document.forms[0].submit();", "javascript");
login.execScript("CheckForm();", "javascript");
string value = webBrowser1.Document.GetElementById("PASSWORD").GetAttribute("value");
encryptPass = value; GetContact();
numtries++;
}
}
if (webBrowser1.Document.GetElementById("userName") == null)
{
numtries = 0; //string cookieString = webBrowser1.Document.Cookie; //CookieCollection cc = new CookieCollection();
//CookieManger.SetCKAppendToCC(cc, cookieString, "http://www.abc.cn:8080");
//cookie.Add(cc); }
}
通过浏览器接口,我们可以实现页面内容在不可以见的浏览器控件中呈现,然后获取相应的页面对象或者页面源码进行分析,可以得到更加丰富的数据,模拟浏览器的实际操作和获得真实的显示结果。
c# 执行js的方法的更多相关文章
- 自动化测试中执行JS脚本方法封装
执行JS脚本方法封装: class JavaScript(Base): def execute_javascript(self, js): """执行 JavaScrip ...
- 终止执行js的方法
(一)在function里面 (1)return;(2)return false; (二)非function方法里面 alert("before error.");throw Sy ...
- ASP.NET 下载文件并继续执行JS解决方法
需求说明:当用户点击按钮时使当前按钮为不可用,并打开新页面,关闭新页面时,按钮变为可用.并且如果不关闭新页面,当前按钮过10秒钟自动变为可用. 包含3个页面: 一.按钮页 前台代码:当刷新后采用js进 ...
- webBrowser执行js的方法,并返回值,c#后台取值
private void Form1_Load(object sender, EventArgs e) { webBrowser1.Navigate(Application.StartupPath + ...
- 【Android】java中调用JS的方法
最近因为学校换了新的教务系统,想做一个模拟登陆功能,发现登陆的账号和密码有一个js脚本来进行加密 整理了一下java中执行JS的方法 智强教务 账号 密码 加密方法 var keyStr = &quo ...
- WinForm程序执行JS代码的多种方法以及使用WebBrowser与JS交互
方法一 使用微软官方组件Interop.MSScriptControl 1.msscript.ocx下载的地址 http://www.microsoft.com/downloads/details ...
- [iOS Hybrid实践:UIWebView中Html中用JS调用OC方法,OC执行JS代码]
原理: 1.JS调用OC 每次webview执行跳转时都会被iOS给拦截,执行下面函数获得系统允许. 因此可以根据跳转信息转给系统,执行相应功能,比如打开相册等. // 网页中的每一个请求都会被触发 ...
- ajax 载入html后不能执行其中的js解决方法
事件背景 有一个公用页面需要在多个页面调用,其中涉及到部分js已经写在了公用页面中,通过ajax加载该页面后无法执行其中的js. 解决思路 1. 采用附加一个iframe的方法去执行js,为我等代码洁 ...
- UIWebView中Html中用JS调用OC方法及OC执行JS代码
HTML代码: <html> <head> <title>HTML中用JS调用OC方法</title> <meta http-equiv=&quo ...
随机推荐
- 模拟SPI协议时序
SPI是串行外设接口总线,摩托罗拉公司开发的一种全双工,同步通信总线,有四线制和三线制. 在单片机系统应用中,单片机常常是被用来当做主机(MASTER),外围器件被当做从机(SLAVE). 所以,在以 ...
- IAR和Keil文件包含路径设置
在模块化编程时,为一个模块单独设置头文件是必不可少的. 在两款主流编译器中,在引用模块函数时候,包含头文件路径是必须的,那么设置文件路径的准确性就显得尤为重要. 否则,编译器会报错,无法打开某某头文件 ...
- hashMap、hashTable、treeMap的区别
1.hashTable是线程安全的.hashMap不是线程安全的 hashmap 线程不安全 允许有null的键和值 效率高一点. 方法不是Synchronize的要提供外同步 有containsva ...
- MyBatis 基本数据类型条件判断问题
1.判断参数使用:_parameter <select id="findCount" parameterType="int" resultType=&qu ...
- 浅谈C/C++引用和指针的联系和区别
为什么C/C++语言使用指针? 答案:①一方面,每一种编程语言都使用指针.不止C/C++使用指针. 每一种编程语言都使用指针.C++将指针暴露给了用户(程序员),而Java和C#等语言则将指针隐藏起来 ...
- Apriori算法-位运算-C语言
原文地址:http://blog.csdn.net/liema2000/article/details/6118423 //////////////////////////////////////// ...
- 第十六节,基本数据类型,字典dict
字典 常用操作: 索引 新增 删除 键.值.键值对 循环 长度 字典由键值对组成,由一个键(名称)和 一个值组成,与列表和元组不同的是里面的元素是有键的(名称) 所以当要打印字典时,打印字典变量加[键 ...
- Varnish && Varnish Cache
1 1 1 Varnish https://www.varnish-cache.org/intro/index.html#intro Introduction to Varnish The basic ...
- python多线程--theading模块
使用Condition对象可以在某些事件触发或者达到特定的条件后才处理数据,Condition除了具有Lock对象的acquire方法和release方法外, 还有wait方法,notify方法,no ...
- 【Machine Learning in Action --2】K-近邻算法构造手写识别系统
为了简单起见,这里构造的系统只能识别数字0到9,需要识别的数字已经使用图形处理软件,处理成具有相同的色彩和大小:宽高是32像素的黑白图像.尽管采用文本格式存储图像不能有效地利用内存空间,但是为了方便理 ...