使用Apache HttpComponents 实现模拟登录

	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;
        }

 
 
二、输入账号密码登录
	可以看到如下请求:
	使用Apache HttpComponents 实现模拟登录_第1张图片
	这里我们可以看到,请求把之前登录页面的cookie传回, 并且将表单信息,用户名和密码传回。
	这里有几点需要注意,输入的密码和这里请求传输的密码并不一致,那么我看查看下相应的表单。可以看到:

	可以看到提交前使用 checkform()进行了处理,我们找到相应的请求,查看源码:
        使用Apache HttpComponents 实现模拟登录_第2张图片
 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.并且获取到登录成功后的主页面。模拟登录成功!
完整源码
 
 
 
 
 

你可能感兴趣的:(使用Apache HttpComponents 实现模拟登录)