[size=large][color=blue]网站登陆分类[/color][/size]
[size=medium]
不考虑HTTPS,网站通过浏览器登陆大约可以分为如下几类
[*] 密码明文传输,用户在浏览器输入用户名密码,然后用明文传输到网站。人人网就是这种做法。
[*] 使用HTTP协议Authentication机制,一般网站使用的少。
[*] 使用JS对用户输入的密码进行处理,网络上不用传输明文密码了。开心001采用的这种做法。
[/size]
[size=large][color=blue]开心001的登陆开发实践[/color][/size]
[size=medium]和人人一样,我在做开心001登陆开始的时候也是使用badboy录制登陆过程,用jmeter重放。发现登陆时并没有直接发送密码明文,而是用如下两个参数代替:[/size]
[quote]encypt
rpasswd[/quote]
[size=medium]猜测开心可能使用了一个encyptKey(encypt)对用户输入的密码进行处理,生成一个rpasswd。通过firebug追踪登陆过程,证实了这个猜想:[color=red]如果用户没有登陆,每次访问登陆页面时,服务器会发一个encyptKey到客户端,返回在网页里(保存成javascript变量的形式),用户输入密码并提交后,会运行一段js代码,这段代码会使用encyptKey对密码进行处理,生成rpasswd参数发送给服务器进行校验。[/color]由于每次访问登陆页面服务器返回的验证码不同,这就使得你在某次录制产生的参数下次就不能登陆。
发现这个问题后,尝试了如下解决方法:
[*] HTTPClient是否能够模拟点击按钮,也就是说用HTTPClient完全模拟用户登陆全过程。遗憾的是,HTTPClient并不支持这个功能。
[*] 是否有其它工具。HTTPUnit可以用了模拟用户点击,但是下载尝试以后,发现HTTPUnit并不好用,这条路没有尝试成功。
[*] 在java中实现开心001网页里js要实现的功能,也就是:首先分析出encyptKey,然后用这个encyptKey加上自己实现js功能部分产生rpasswd,再发送到服务器验证。但是开心001关于验证的js100多行,涉及大量位运算,在java里无bug的实现还是需要相当工作量的。
[*] 经过仔细考虑,想到: 如果在java里面可以调用js,那么直接调用js的功能产生rpasswd不就可以了吗? 很快就找到rhino这个工具,实践中这个工具非常好用,让人再一次感到了做java程序员的快乐 :)
[size=large][color=blue]最终的登陆流程[/color][/size]
[size=medium]
- [*] 登陆页面,找到登陆页面中关于验证这块的js代码,并保存放到java可以访问的地方
[*] 访问登陆页面,从页面中分割出encyptKey
[*] 使用rhino访问前面保存的js,使用encyptKey产生服务器需要的参数rpasswd
[*] 向服务器发送参数进行验证
[size=medium]源码参考附件,运行前加一下开心的账号和密码。[/size]
[size=large][color=blue]验证码问题 (补充)[/color][/size]
[size=medium]上一个帖子里,很多人问到验证码问题,关于验证码,个人简单看法如下:
[*]很多大网站为了提高用户体验在用户第一次登陆时不要求用户输入验证码。只有在用户密码输入错误后,才会要求输入验证码。
[*]如果验证码是服务器端产生的,除了分析图片,也没有更好的方法,如果验证码是客户端产生的,比如: 使用js产生的,可以使用rhino来模拟得到这个验证码。
[*]一般来说,登陆后,大部分网页都可以访问,大部分操作都可以模拟。但是有些操作,比如说发文章,通常要求输入验证码,就比较难做到自动化。如果你发现哪个网站写文章不要去输入验证码,你就去写个机器人去刷屏吧,就象javaeye的问答频道一样 :)
[size=medium][color=red]注: Foxswily提供了一个更好的工具HTMLUnit,直接模拟点击网页,我没有实践过,建议大家可以试一下。
http://www.iteye.com/topic/644353
有人提到Selenium,这个我以前没有用过,看起来不错,有空可以试一下。
[/color][/size]