使用Apache HttpComponents 实现模拟登录

来源:互联网 发布:php strcamp == 编辑:程序博客网 时间:2024/06/16 11:51
HttpComponents也就是以前的httpclient项目,可以用来提供高效的、最新的、功能丰富的支持 HTTP 协议的客户端/服务器编程工具包,并且它支持 HTTP 协议最新的版本和建议。
本文将使用目前最新版本4.3.1 来实现网站的模拟登录。将以川农教务管理系统为例,这个系统有些情况有比较好的说明性。使用到的一些工具和必要信息有:
1、chrome浏览器,用于调试每次发送的请求。
2、登录该系统的用户名和密码,用于跟踪正常登录流程。
一、打开登录页面
    使用chrome可以看到,打开此页面时向本地写入了一个cookie.
    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;        }

二、输入账号密码登录
可以看到如下请求:
request
这里我们可以看到,请求把之前登录页面的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:
  1. 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.并且获取到登录成功后的主页面。模拟登录成功!
完整源码
	
				
		
原创粉丝点击