您的位置:首页 > 理论基础 > 计算机网络

使用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.并且获取到登录成功后的主页面。模拟登录成功!
完整源码

                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: