使用Apache HttpComponents 实现模拟登录
2013-10-19 14:57
183 查看
HttpComponents也就是以前的httpclient项目,可以用来提供高效的、最新的、功能丰富的支持 HTTP 协议的客户端/服务器编程工具包,并且它支持 HTTP 协议最新的版本和建议。
本文将使用目前最新版本4.3.1 来实现网站的模拟登录。将以川农教务管理系统为例,这个系统有些情况有比较好的说明性。使用到的一些工具和必要信息有:1、chrome浏览器,用于调试每次发送的请求。2、登录该系统的用户名和密码,用于跟踪正常登录流程。
一、打开登录页面
使用chrome可以看到,打开此页面时向本地写入了一个cookie.
我们可以使用HttpGet来获取该cookie信息,代码大致如下:
private String getCookie() throws ClientProtocolException, IOException{ HttpGet indexGet = new HttpGet("http://jiaowu.sicau.edu.cn/web/web/web/index.asp"); HttpResponse indexRes = client.execute(indexGet); this.cookie = indexRes.getHeaders("Set-Cookie")[0].getValue(); indexGet.releaseConnection(); return cookie; }
二、输入账号密码登录
可以看到如下请求:
这里我们可以看到,请求把之前登录页面的cookie传回, 并且将表单信息,用户名和密码传回。
这里有几点需要注意,输入的密码和这里请求传输的密码并不一致,那么我看查看下相应的表单。可以看到:
可以看到提交前使用 checkform()进行了处理,我们找到相应的请求,查看源码:
checkform()将密码进行编码转化,然后传输。但是细心一点就会发现,当刷新页面时会看到checkform()里面的dcode2这个基数会变化,也就是说checkform是一个动态生成的方法。这样的话,我们必须每次动态去获取这个js,然后将我们自己的密码转化后传给表单的请求路径。
private String getbaseDcode() throws IOException{ String baseDcode = ""; HttpGet jsGet = new HttpGet("http://jiaowu.sicau.edu.cn/jiaoshi/bangong/js/"); HttpResponse jsRes = client.execute(jsGet); HttpEntity jsEntity = jsRes.getEntity(); InputStream in = jsEntity.getContent(); BufferedReader reader = new BufferedReader(new InputStreamReader(in)); String temp = reader.readLine(); while(temp!=null){ if(temp.matches("^dcode2=\\d+$")){ baseDcode = temp.replaceAll("dcode2=", ""); System.out.println("[Info] basedcode:"+baseDcode); break; } temp = reader.readLine(); } jsGet.releaseConnection(); return baseDcode; }
通过getbaseDcode()我们可以动态获取这个基数,然后使用decode()获取编码后的密码:
private String decode(BigInteger baseDecode,String pwd){ String dcode = ""; baseDecode=baseDecode.multiply(new BigInteger("137")); String baseDecodeString = baseDecode+""; String tmpstr; int dcodelen =pwd.length(); for (int i=1;i<=dcodelen;i++){ tmpstr = pwd.substring(i-1,i); dcode+=(char)((int)tmpstr.charAt(0)-i-Integer.parseInt(baseDecodeString.substring(i-1,i))); } return dcode; }到现在为止,我们已经封装好了参数,可以向验证路径进行提交:
List <NameValuePair> nvps = new ArrayList <NameValuePair>(); nvps.add(new BasicNameValuePair("user", userName)); nvps.add(new BasicNameValuePair("pwd", password)); HttpPost httpPost = new HttpPost( "http://jiaowu.sicau.edu.cn/jiaoshi/bangong/check.asp" ); httpPost.setEntity(new UrlEncodedFormEntity(nvps)); httpPost.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.69 Safari/537.36"); httpPost.setHeader("Host","jiaowu.sicau.edu.cn"); httpPost.setHeader("Cookie", cookie); HttpResponse response = client.execute(httpPost); if(response.getStatusLine().getStatusCode()==200){ System.out.println("[Info] Login success."); }我们先来发送一次请求,看看结果:
得到的却是一个跳转过程页面,即:
window.location.href="../index.asp"类似这样的结果。再次看看我们提交表单的请求,可以发现,这次请求返回的302,有跳转。
我们可以设置httpclient来达到自动处理跳转,
builder.setRedirectStrategy(new LaxRedirectStrategy());当然也可以自己处理跳转,获取响应的location:Location:../../../xuesheng/dangan/banji/xiangxi.asp然后将之前的请求转发过去。
现在我们在发送一次请求,但是得到的却是:
防火墙拦截等信息.
将登录后的地址,在同浏览器的不同标签打开,正常的话会进入登录后的页面,但是同样的我们得到防火墙拦截信息。仔细对比下两次的请求发现
正常访问的页面的inititator为之前我们登录前的网址,而得到防火墙拦截信息的请求的initiator是other,找到不同点了。ok,再来看下表单提交请求,这里有一个referer的请求头。
Referer表示,该请求是由什么来发起的。
设置Referer请求头:
httpPost.setHeader("Referer","http://jiaowu.sicau.edu.cn/web/web/web/index.asp");
再次发送请求,返回200 ok.并且获取到登录成功后的主页面。模拟登录成功!
完整源码
相关文章推荐
- PHP cURL实现模拟登录与采集使用方法详解教程
- mysql实操(一)—使用存储过程模拟实现用户登录
- CAS协议介绍和在apache使用cas实现单点登录sso
- PHP使用CURL实现对带有验证码的网站进行模拟登录的方法
- python3下使用scrapy实现模拟用户登录与cookie存储 —— 基础篇(马蜂窝)
- 使用Apache AB实现bugfree登录的脚本
- 使用WinHttp实现POST方式用户模拟登录网站
- hp 使用curl模拟登录discuz以及模拟发帖(含formhash的实现)
- Java编程练习:使用分层结构,基于XML文件,实现模拟用户登录
- 使用HttpWebRequest和HttpWebResponse实现模拟登录需要登陆后才可以访问的页面
- JavaWeb_使用Cookie模拟实现自动登录
- 使用Scrapy实现模拟登录的方法
- PHP使用CURL实现对带有验证码的网站进行模拟登录的方法
- C语言 编写代码实现,模拟用户登录场景 ( for循环,if语句的使用)
- 这是一个使用mvp模式实现模拟用户登录的简单Demo。
- PHP使用CURL实现对带有验证码的网站进行模拟登录的方法
- PHP cURL应用实现模拟登录与采集使用方法详解
- python3下使用scrapy实现模拟用户登录与cookie存储—— 中级篇(百度云俱乐部)
- PHP使用Curl实现模拟登录及抓取数据功能示例
- PHP使用CURL实现对带有验证码的网站进行模拟登录的方法