`
robertliudeqiang
  • 浏览: 121885 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

HTTPClient模拟登陆开心网001

    博客分类:
  • web
阅读更多
网站登陆分类

不考虑HTTPS,网站通过浏览器登陆大约可以分为如下几类
  • 密码明文传输,用户在浏览器输入用户名密码,然后用明文传输到网站。人人网就是这种做法。
  • 使用HTTP协议Authentication机制,一般网站使用的少。
  • 使用JS对用户输入的密码进行处理,网络上不用传输明文密码了。开心001采用的这种做法。
另外: 有些网站也提供接口,让用户可以编写客户端来访问网站,例如amazon s3。



开心001的登陆开发实践

和人人一样,我在做开心001登陆开始的时候也是使用badboy录制登陆过程,用jmeter重放。发现登陆时并没有直接发送密码明文,而是用如下两个参数代替:
引用
encypt
rpasswd

猜测开心可能使用了一个encyptKey(encypt)对用户输入的密码进行处理,生成一个rpasswd。通过firebug追踪登陆过程,证实了这个猜想:如果用户没有登陆,每次访问登陆页面时,服务器会发一个encyptKey到客户端,返回在网页里(保存成javascript变量的形式),用户输入密码并提交后,会运行一段js代码,这段代码会使用encyptKey对密码进行处理,生成rpasswd参数发送给服务器进行校验。由于每次访问登陆页面服务器返回的验证码不同,这就使得你在某次录制产生的参数下次就不能登陆。

发现这个问题后,尝试了如下解决方法:
  • HTTPClient是否能够模拟点击按钮,也就是说用HTTPClient完全模拟用户登陆全过程。遗憾的是,HTTPClient并不支持这个功能。
  • 是否有其它工具。HTTPUnit可以用了模拟用户点击,但是下载尝试以后,发现HTTPUnit并不好用,这条路没有尝试成功。
  • 在java中实现开心001网页里js要实现的功能,也就是:首先分析出encyptKey,然后用这个encyptKey加上自己实现js功能部分产生rpasswd,再发送到服务器验证。但是开心001关于验证的js100多行,涉及大量位运算,在java里无bug的实现还是需要相当工作量的。
  • 经过仔细考虑,想到: 如果在java里面可以调用js,那么直接调用js的功能产生rpasswd不就可以了吗? 很快就找到rhino这个工具,实践中这个工具非常好用,让人再一次感到了做java程序员的快乐

最终的登陆流程

  • 登陆页面,找到登陆页面中关于验证这块的js代码,并保存放到java可以访问的地方
  • 访问登陆页面,从页面中分割出encyptKey
  • 使用rhino访问前面保存的js,使用encyptKey产生服务器需要的参数rpasswd
  • 向服务器发送参数进行验证

源码参考附件,运行前加一下开心的账号和密码。


验证码问题 (补充)
上一个帖子里,很多人问到验证码问题,关于验证码,个人简单看法如下:
  • 很多大网站为了提高用户体验在用户第一次登陆时不要求用户输入验证码。只有在用户密码输入错误后,才会要求输入验证码。
  • 如果验证码是服务器端产生的,除了分析图片,也没有更好的方法,如果验证码是客户端产生的,比如: 使用js产生的,可以使用rhino来模拟得到这个验证码。
  • 一般来说,登陆后,大部分网页都可以访问,大部分操作都可以模拟。但是有些操作,比如说发文章,通常要求输入验证码,就比较难做到自动化。如果你发现哪个网站写文章不要去输入验证码,你就去写个机器人去刷屏吧,就象javaeye的问答频道一样


注: Foxswily提供了一个更好的工具HTMLUnit,直接模拟点击网页,我没有实践过,建议大家可以试一下。
http://www.iteye.com/topic/644353

有人提到Selenium,这个我以前没有用过,看起来不错,有空可以试一下。
分享到:
评论
25 楼 bestdqf 2011-07-01  
我现在想模拟登录久游网 但是一直没有成功 http://www.iteye.com/problems/67643 这是我的提问 麻烦你帮我看看  具体问题我都在里面描述了
24 楼 alosin 2011-03-21  
最近一直在研究这个,对于有验证码的,我带cookie去访问也校验失败,真是无法预知后台的实现,当然这个网站对于抓取它的数据 也是做了特别处理(去抓别个网站的数据 嘿嘿)
楼主 对于这种情况有什么好的建议没?
23 楼 luyuwww 2011-03-15  
看起来不错,有空可以试一下。
22 楼 liubey 2011-03-15  
好贴~ 做个记号 正好想研究下开心网
21 楼 libingye 2011-02-14  
之前写过发帖机的东西,不过用的是C#..
后来发现,发帖这东西,最大的限制还是在服务端,服务端改点东西,你就要研究个大半天。。。
20 楼 zhengliweb 2010-12-02  
import sun.org.mozilla.javascript.*;在sun jdk1.6以后已经包含关于mozilla的javascript包,期待什么时候有空指导下xiaoyou.qq的登陆~~
19 楼 yfnok 2010-07-13  
你好,我想問下,如果是Http登陸協議認證方式,該如何測試系統呢?
18 楼 yvfish 2010-04-16  
不用楼主那么麻烦吧,Selenium这个东西还是很好很强大滴~
17 楼 spook99 2010-04-15  
我有一点不明白,我直接调用post请求,就可以成功登陆。有这么复杂吗?

我写了个例子,没有问题啊
16 楼 chenkan2000 2010-04-15  
http抓取工具:
HttpWatcher:IE插件方式,界面和功能都很好,还能自己编程扩展。抓取特殊格式的二进制流有问题(如amf),它会自作主张的转成字符。
tcpmon:apache开发,用地不多,感觉可以。
grinder 3.3:开源测试工具,用TCPProxy抓取,可以得到二进制流
15 楼 Foxswily 2010-04-15  
<div class="quote_title">robertliudeqiang 写道</div>
<div class="quote_div">
<div class="quote_title">Foxswily 写道</div>
<div class="quote_div">有更简单的实现<br>htmlunit  http://htmlunit.sourceforge.net/<br>可以模拟点击按钮等等,属于在httpclient更高一层的应用,本意用于测试,实际用来模拟登录效果异常的好。</div>
<br><br>HTTPUnit这个工具很早就研究过,主要是想做一些系统测试方面的工作,当时觉得并不好用,后来还是没有应用到项目里面。<br><br>做开心登陆时,也想到过使用这个工具,实践中发现还是不好用,最新版的下载下来一些简单的例子也运行出错。个人觉得这个工具维护的不好,最近一次更新还是在2008年。<br><br>可能还是不太会用这个工具吧,你要有好的经验可以贴出来共享一下。</div>
<p><br><br>单独开贴写了写,参见 <a href="/topic/644353" target="_blank">http://www.iteye.com/topic/644353</a></p>
<p> </p>
14 楼 Weich_JavaDeveloper 2010-04-15  
我去给你问不就知道了。。。哈哈。。。就在我们公司对面。。。前台MM很正哦。。。
13 楼 zhaomingzm_23 2010-04-15  
robertliudeqiang 写道
fengsky491 写道
问问,有没有工具能够监测c/s客户端的登录过程

ps:我现在玩的是三国策6,一直不知道怎么做个自动登陆器,badboy好像只对网页有效


不好意思,没搞过。 



可以用IBM 的 Rational Performance Tester 自我感觉很有用,可以随意的抓包分析,并可以结合Eclipse定制代码,有兴趣的一起研究下。
12 楼 xiaoyiz 2010-04-14  
robertliudeqiang 写道
Foxswily 写道
有更简单的实现
htmlunit  http://htmlunit.sourceforge.net/
可以模拟点击按钮等等,属于在httpclient更高一层的应用,本意用于测试,实际用来模拟登录效果异常的好。


HTTPUnit这个工具很早就研究过,主要是想做一些系统测试方面的工作,当时觉得并不好用,后来还是没有应用到项目里面。

做开心登陆时,也想到过使用这个工具,实践中发现还是不好用,最新版的下载下来一些简单的例子也运行出错。个人觉得这个工具维护的不好,最近一次更新还是在2008年。

可能还是不太会用这个工具吧,你要有好的经验可以贴出来共享一下。


Introduction
The dependencies page lists all the jars that you will need to have in your classpath.

The class com.gargoylesoftware.htmlunit.WebClient is the main starting point. This simulates a web browser and will be used to execute all of the tests.

Most unit testing will be done within a framework like JUnit so all the examples here will assume that we are using that.

In the first sample, we create the web client and have it load the homepage from the HtmlUnit website. We then verify that this page has the correct title. Note that getPage() can return different types of pages based on the content type of the returned data. In this case we are expecting a content type of text/html so we cast the result to an com.gargoylesoftware.htmlunit.html.HtmlPage.

@Test
public void homePage() throws Exception {
    final WebClient webClient = new WebClient();
    final HtmlPage page = webClient.getPage("http://htmlunit.sourceforge.net");
    assertEquals("HtmlUnit - Welcome to HtmlUnit", page.getTitleText());

    final String pageAsXml = page.asXml();
    assertTrue(pageAsXml.contains("<body class=\"composite\">"));

    final String pageAsText = page.asText();
    assertTrue(pageAsText.contains("Support for the HTTP and HTTPS protocols"));
}Imitating a specific browser
Often you will want to simulate a specific browser. This is done by passing a com.gargoylesoftware.htmlunit.BrowserVersion into the WebClient constructor. Constants have been provided for some common browsers but you can create your own specific version by instantiating a BrowserVersion.

@Test
public void homePage_Firefox() throws Exception {
    final WebClient webClient = new WebClient(BrowserVersion.FIREFOX_2);
    final HtmlPage page = webClient.getPage("http://htmlunit.sourceforge.net");
    assertEquals("HtmlUnit - Welcome to HtmlUnit", page.getTitleText());
}Specifying this BrowserVersion will change the user agent header that is sent up to the server and will change the behavior of some of the JavaScript.

Finding a specific element
Once you have a reference to an HtmlPage, you can search for a specific HtmlElement by one of 'get' methods, or by using XPath.

Below is an example of finding a 'div' by an ID, and getting an anchor by name:

@Test
public void getElements() throws Exception {
    final WebClient webClient = new WebClient();
    final HtmlPage page = webClient.getPage("http://some_url");
    final HtmlDivision div = page.getHtmlElementById("some_div_id");
    final HtmlAnchor anchor = page.getAnchorByName("anchor_name");
}XPath is the suggested way for more complex searches, a brief tutorial can be found in W3Schools

@Test
public void xpath() throws Exception {
    final WebClient webClient = new WebClient();
    final HtmlPage page = webClient.getPage("http://htmlunit.sourceforge.net");

    //get list of all divs
    final List<?> divs = page.getByXPath("//div");

    //get div which has a 'name' attribute of 'John'
    final HtmlDivision div = (HtmlDivision) page.getByXPath("//div[@name='John']").get(0);
}Using a proxy server
The last WebClient constructor allows you to specify proxy server information in those cases where you need to connect through one.

@Test
public void homePage_proxy() throws Exception {
    final WebClient webClient = new WebClient(BrowserVersion.FIREFOX_2, "http://myproxyserver", myProxyPort);

    //set proxy username and password
    final DefaultCredentialsProvider credentialsProvider = (DefaultCredentialsProvider) webClient.getCredentialsProvider();
    credentialsProvider.addProxyCredentials("username", "password");

    final HtmlPage page = webClient.getPage("http://htmlunit.sourceforge.net");
    assertEquals("HtmlUnit - Welcome to HtmlUnit", page.getTitleText());
}Specifying this BrowserVersion will change the user agent header that is sent up to the server and will change the behavior of some of the JavaScript.

Submitting a form
Frequently we want to change values in a form and submit the form back to the server. The following example shows how you might do this.

@Test
public void submittingForm() throws Exception {
    final WebClient webClient = new WebClient();

    // Get the first page
    final HtmlPage page1 = webClient.getPage("http://some_url");

    // Get the form that we are dealing with and within that form,
    // find the submit button and the field that we want to change.
    final HtmlForm form = page1.getFormByName("myform");

    final HtmlSubmitInput button = form.getInputByName("submitbutton");
    final HtmlTextInput textField = form.getInputByName("userid");

    // Change the value of the text field
    textField.setValueAttribute("root");

    // Now submit the form by clicking the button and get back the second page.
    final HtmlPage page2 = button.click();
}
11 楼 robertliudeqiang 2010-04-14  
Foxswily 写道
有更简单的实现
htmlunit  http://htmlunit.sourceforge.net/
可以模拟点击按钮等等,属于在httpclient更高一层的应用,本意用于测试,实际用来模拟登录效果异常的好。


HTTPUnit这个工具很早就研究过,主要是想做一些系统测试方面的工作,当时觉得并不好用,后来还是没有应用到项目里面。

做开心登陆时,也想到过使用这个工具,实践中发现还是不好用,最新版的下载下来一些简单的例子也运行出错。个人觉得这个工具维护的不好,最近一次更新还是在2008年。

可能还是不太会用这个工具吧,你要有好的经验可以贴出来共享一下。
10 楼 gstarwd 2010-04-14  
Foxswily 写道
有更简单的实现
htmlunit  http://htmlunit.sourceforge.net/
可以模拟点击按钮等等,属于在httpclient更高一层的应用,本意用于测试,实际用来模拟登录效果异常的好。

哇~~~
9 楼 Foxswily 2010-04-14  
有更简单的实现
htmlunit  http://htmlunit.sourceforge.net/
可以模拟点击按钮等等,属于在httpclient更高一层的应用,本意用于测试,实际用来模拟登录效果异常的好。
8 楼 robertliudeqiang 2010-04-14  
fengsky491 写道
问问,有没有工具能够监测c/s客户端的登录过程

ps:我现在玩的是三国策6,一直不知道怎么做个自动登陆器,badboy好像只对网页有效


不好意思,没搞过。 
7 楼 robertliudeqiang 2010-04-14  
whaosoft 写道
哈哈 你又发这个了 呵呵 支持你 在多写点功能


呵呵,基本上没有什么续集了。对豆瓣的API有点兴趣,不过没时间搞了。
6 楼 fengsky491 2010-04-14  
问问,有没有工具能够监测c/s客户端的登录过程

ps:我现在玩的是三国策6,一直不知道怎么做个自动登陆器,badboy好像只对网页有效

相关推荐

Global site tag (gtag.js) - Google Analytics