`
michaeltangbin
  • 浏览: 268109 次
  • 性别: Icon_minigender_1
  • 来自: 黑龙江省
社区版块
存档分类
最新评论

Apache HttpClient模拟登录

    博客分类:
  • java
阅读更多

Apache HttpClient模拟登录

    HttpClient 是 Apache Jakarta Common 下的子项目,可以用来提供高效的、最新的、功能丰富的支持 HTTP 协议的客户端编程工具包,并且它支持 HTTP 协议最新的版本和建议。

HttpClient 功能介绍

以下列出的是 HttpClient 提供的主要的功能,要知道更多详细的功能可以参见 HttpClient 的主页。

  • 实现了所有 HTTP 的方法(GET,POST,PUT,HEAD 等)
  • 支持自动转向
  • 支持 HTTPS 协议
  • 支持代理服务器等

下面将逐一介绍怎样使用这些功能。首先,我们必须安装好 HttpClient。

下面是个我写的程序:
package com.newpalm.unicomfetch.threads;
import java.util.Vector;
import org.apache.commons.httpclient.Cookie;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.cookie.CookiePolicy;
import org.apache.commons.httpclient.cookie.CookieSpec;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.htmlparser.Node;
import org.htmlparser.Parser;
import org.htmlparser.tags.TableColumn;
import org.htmlparser.tags.TableRow;
import org.htmlparser.tags.TableTag;
import org.htmlparser.visitors.ObjectFindingVisitor;
/**
 * 用来演示登录表单的示例
 * @author Liudong
 */
public class FormLoginDemo {
   
    public static void main(String[] args) throws Exception{
     Parser parser = null;
     ObjectFindingVisitor visitor = null;
        HttpClient client = new HttpClient();
       
        //模拟登录页面
        PostMethod post = new PostMethod("http://211.90.119.58:9999/SPLogin.aspx ");
        NameValuePair name = new NameValuePair("txtHandsetNumber", "123456");    
        NameValuePair pass = new NameValuePair("txtPassword", "123456");
        NameValuePair __VIEWSTATE = new NameValuePair("__VIEWSTATE", "dDwtMTUxMzkxNTQ0Mzt0PDtsPGk8MT47PjtsPHQ8O2w8aTwxPjs+O2w8dDxwPGw8VGV4dDs+O2w8XDxtYXJxdWVlIERpcmVjdGlvbj0idXAiIGJlaGF2aW9yPSJzY3JvbGwiICBoZWlnaHQ9JzE1MCcgc2Nyb2xsZGVsYXk9MzAwIG9ubW91c2VvdmVyPSd0aGlzLnN0b3AoKScgb25tb3VzZW91dD0ndGhpcy5zdGFydCgpJ1w+XDxpbWcgc3JjPSJpbWFnZS9kZWZhdWx0X2NhbGxfaWNvbi5naWYiIHdpZHRoPSI0IiBoZWlnaHQ9IjciXD4mbmJzcFw7Jm5ic3BcO1w8YSBocmVmID0iIyIgb25jbGljaz0ib3BlbldpbmRvdygnL0J1bGxldGluLmFzcHg/QnVsbGV0aW5JZD0yMycpIlw+c3DkuJrliqHmjqXlhaXms6jmhI/kuovpoblcPC9hXD4KXDxiclw+XDxiclw+XDwvbWFycXVlZVw+Oz4+Ozs+Oz4+Oz4+O2w8YnRuTG9naW47Pj4pKEgdIvj1JmRdgJaS7sGzD39jZg==");
        NameValuePair btnLoginx = new NameValuePair("btnLogin.x", "0");
        NameValuePair btnLoginy = new NameValuePair("btnLogin.y", "5");
        post.setRequestBody(new NameValuePair[]{name,pass,__VIEWSTATE,btnLoginx,btnLoginy});
        int status = client.executeMethod(post);
       
        post.releaseConnection(); 
        //查看cookie信息
        CookieSpec cookiespec = CookiePolicy.getDefaultSpec();
        Cookie[] cookies = client.getState().getCookies();
        if (cookies.length == 0) {
           System.out.println("None");   
        } else {
           for (int i = 0; i < cookies.length; i++) {
              System.out.println(cookies[i].toString());   
           }
       }
       
       //访问所需的页面
        GetMethod get = new GetMethod("http://211.90.119.58:9999/PhoneSearch/PhoneSearch.aspx ");
        client.executeMethod(get);
        visitor = new ObjectFindingVisitor(TableTag.class);
  parser = new Parser();
  parser.setInputHTML(get.getResponseBodyAsString());
  parser.setEncoding("GBK");
  parser.visitAllNodesWith(visitor);
  
  //取得要解析的页面数
  Node[] tables = visitor.getTags();
  TableTag tableTag = (TableTag) tables[tables.length-1];
  TableRow[] rows = tableTag.getRows();
  TableRow row = rows[0];
  TableColumn[] col = row.getColumns();
  int pageNumber = Integer.parseInt(col[0].getChildrenHTML().substring(25, 29));
  get.releaseConnection();
  
  for(int i=1;i<pageNumber;i++){
   PostMethod pt = new PostMethod("http://211.90.119.58:9999/PhoneSearch/PhoneSearch.aspx ");   
   NameValuePair txtPage = new NameValuePair("txtPage",Integer.toString(i));
         __VIEWSTATE = new NameValuePair("__VIEWSTATE", "")
         NameValuePair __EVENTTARGET = new NameValuePair("__EVENTTARGET", "");
         NameValuePair __EVENTARGUMENT = new NameValuePair("__EVENTARGUMENT", "");
         NameValuePair TBMDN = new NameValuePair("TBMDN", "");
         NameValuePair TBServiceType = new NameValuePair("TBServiceType", "");
         NameValuePair TBStartTime = new NameValuePair("TBStartTime", "");
         NameValuePair TBEndTime = new NameValuePair("TBEndTime", "");
         NameValuePair btnGotox = new NameValuePair("btnGoto.x", "26");
         NameValuePair btnGotoy = new NameValuePair("btnGoto.y", "13");
         pt.setRequestBody(new NameValuePair[]{__EVENTTARGET,__EVENTARGUMENT,__VIEWSTATE,TBMDN,TBServiceType,TBStartTime,TBEndTime,txtPage,btnGotox,btnGotoy});
         int a = client.executeMethod(pt);
        
        
         parser.setInputHTML(pt.getResponseBodyAsString());
   parser.setEncoding("GBK");
   parser.visitAllNodesWith(visitor);
   
   tables = visitor.getTags();
   tableTag = (TableTag) tables[tables.length-3];
   
   rows = tableTag.getRows();
   row = rows[1];
   col = row.getColumns();
   System.out.println(col[4].getChildrenHTML().toString());
         get.releaseConnection();
  }
       
    }
}
 

使用HttpClient过程中常见的一些问题

下面介绍在使用HttpClient过程中常见的一些问题。

字符编码

某目标页的编码可能出现在两个地方,第一个地方是服务器返回的http头中,另外一个地方是得到的html/xml页面中。

  • 在http头的Content-Type字段可能会包含字符编码信息。例如可能返回的头会包含这样子的信息:Content-Type: text/html; charset=UTF-8。这个头信息表明该页的编码是UTF-8,但是服务器返回的头信息未必与内容能匹配上。比如对于一些双字节语言国家,可能服务 器返回的编码类型是UTF-8,但真正的内容却不是UTF-8编码的,因此需要在另外的地方去得到页面的编码信息;但是如果服务器返回的编码不是UTF- 8,而是具体的一些编码,比如gb2312等,那服务器返回的可能是正确的编码信息。通过method对象的getResponseCharSet()方 法就可以得到http头中的编码信息。
  • 对于象xml或者html这样的文件,允许作者在页面中直接指定编码类型。比如在html中会有<meta http-equiv="Content-Type" content="text/html; charset=gb2312"/>这样的标签;或者在xml中会有<?xml version="1.0" encoding="gb2312"?>这样的标签,在这些情况下,可能与http头中返回的编码信息冲突,需要用户自己判断到底那种编码类型应该 是真正的编码。

自动转向

根据RFC2616中对自动转向的定义,主要有两种:301和302。301表示永久的移走(Moved Permanently),当返回的是301,则表示请求的资源已经被移到一个固定的新地方,任何向该地址发起请求都会被转到新的地址上。302表示暂时 的转向,比如在服务器端的servlet程序调用了sendRedirect方法,则在客户端就会得到一个302的代码,这时服务器返回的头信息中 location的值就是sendRedirect转向的目标地址。

HttpClient支持自动转向处理,但是象POST和PUT方式这种要求接受后继服务的请求方式,暂时不支持自动转向,因此如果碰到POST方 式提交后返回的是301或者302的话需要自己处理。就像刚才在POSTMethod中举的例子:如果想进入登录BBS后的页面,必须重新发起登录的请 求,请求的地址可以在头字段location中得到。不过需要注意的是,有时候location返回的可能是相对路径,因此需要对location返回的 值做一些处理才可以发起向新地址的请求。

另外除了在头中包含的信息可能使页面发生重定向外,在页面中也有可能会发生页面的重定向。引起页面自动转发的标签是:<meta http-equiv="refresh" content="5; url=http://www.ibm.com/us">。如果你想在程序中也处理这种情况的话得自己分析页面来实现转向。需要注意的是,在上面那 个标签中url的值也可以是一个相对地址,如果是这样的话,需要对它做一些处理后才可以转发。

处理HTTPS协议

HttpClient提供了对SSL的支持,在使用SSL之前必须安装JSSE。在Sun提供的1.4以后的版本中,JSSE已经集成到JDK中, 如果你使用的是JDK1.4以前的版本则必须安装JSSE。JSSE不同的厂家有不同的实现。下面介绍怎么使用HttpClient来打开Https连 接。这里有两种方法可以打开https连接,第一种就是得到服务器颁发的证书,然后导入到本地的keystore中;另外一种办法就是通过扩展 HttpClient的类来实现自动接受证书。

方法1,取得证书,并导入本地的keystore:

  • 安装JSSE (如果你使用的JDK版本是1.4或者1.4以上就可以跳过这一步)。本文以IBM的JSSE为例子说明。先到IBM网站上下载JSSE的安装包。然后解 压开之后将ibmjsse.jar包拷贝到<java-home>\lib\ext\目录下。
  • 取得并且导入证书。证书可以通过IE来获得:

    1. 用IE打开需要连接的https网址,会弹出如下对话框:

    2. 单击"View Certificate",在弹出的对话框中选择"Details",然后再单击"Copy to File",根据提供的向导生成待访问网页的证书文件

    3. 向导第一步,欢迎界面,直接单击"Next",

    4. 向导第二步,选择导出的文件格式,默认,单击"Next",

    5. 向导第三步,输入导出的文件名,输入后,单击"Next",

    6. 向导第四步,单击"Finish",完成向导

    7. 最后弹出一个对话框,显示导出成功

  • 用keytool工具把刚才导出的证书倒入本地keystore。Keytool命令在<java-home>\bin\下,打开命令行窗口,并到<java-home>\lib\security\目录下,运行下面的命令:

    
    keytool -import -noprompt -keystore cacerts -storepass changeit -alias yourEntry1 -file your.cer
    
    
    

    其中参数alias后跟的值是当前证书在keystore中的唯一标识符,但是大小写不区分;参数file后跟的是刚才通过IE导出的证书所在的路径和文件名;如果你想删除刚才导入到keystore的证书,可以用命令:

    
    keytool -delete -keystore cacerts -storepass changeit -alias yourEntry1
    
    
    

  • 写程序访问https地址。如果想测试是否能连上https,只需要稍改一下GetSample例子,把请求的目标变成一个https地址。
    
    GetMethod getMethod = new GetMethod("https://www.yourdomain.com");
    
    
    

    运行该程序可能出现的问题:

    1. 抛出异常java.net.SocketException: Algorithm SSL not available。出现这个异常可能是因为没有加JSSEProvider,如果用的是IBM的JSSE Provider,在程序中加入这样的一行:

    
     if(Security.getProvider("com.ibm.jsse.IBMJSSEProvider") == null)
     Security.addProvider(new IBMJSSEProvider());
     
    
    

    或者也可以打开<java-home>\lib\security\java.security,在行

    
    security.provider.1=sun.security.provider.Sun
    security.provider.2=com.ibm.crypto.provider.IBMJCE
    
    
    

    后面加入security.provider.3=com.ibm.jsse.IBMJSSEProvider

    2. 抛出异常java.net.SocketException: SSL implementation not available。出现这个异常可能是你没有把ibmjsse.jar拷贝到<java-home>\lib\ext\目录下。

    3. 抛出异常javax.net.ssl.SSLHandshakeException: unknown certificate。出现这个异常表明你的JSSE应该已经安装正确,但是可能因为你没有把证书导入到当前运行JRE的keystore中,请按照前 面介绍的步骤来导入你的证书。

方法2,扩展HttpClient类实现自动接受证书

因为这种方法自动接收所有证书,因此存在一定的安全问题,所以在使用这种方法前请仔细考虑您的系统的安全需求。具体的步骤如下:

  • 提供一个自定义的socket factory(test.MySecureProtocolSocketFactory)。这个自定义的类必须实现接口 org.apache.commons.httpclient.protocol.SecureProtocolSocketFactory,在实现接口 的类中调用自定义的X509TrustManager(test.MyX509TrustManager),这两个类可以在随本文带的附件中得到
  • 创建一个org.apache.commons.httpclient.protocol.Protocol的实例,指定协议名称和默认的端口号
    
    Protocol myhttps = new Protocol("https", new MySecureProtocolSocketFactory (), 443);
    
    
    

  • 注册刚才创建的https协议对象
    
    Protocol.registerProtocol("https ", myhttps);
    
    
    

  • 然后按照普通编程方式打开https的目标地址,代码请参见test.NoCertificationHttpsGetSample

处理代理服务器

HttpClient中使用代理服务器非常简单,调用HttpClient中setProxy方法就可以,方法的第一个参数是代理服务器地址,第二个参数是端口号。另外HttpClient也支持SOCKS代理。

分享到:
评论

相关推荐

    用HttpClient来模拟浏览器GET POST

    当然了,正如前面说到的,如果我们自己使用java.net.HttpURLConnection来搞定这些问题是很恐怖的事情,因此在开始之前我们先要介绍一下一个开放源码的项目,这个项目就是Apache开源组织中的httpclient,它隶属于...

    HttpClientMock:用于模拟Apache HttpClient的库

    要模拟HttpClient 4.x,请使用HttpClientMock1.X。 要模拟HttpClient 5.x,请使用HttpClientMock2.X。 用法 记录 使用HttpClientMock首先定义客户端行为。 在受测代码开始之前,HttpClientMock必须知道如何响应...

    Jsoup+httpclient 模拟登陆和抓取

    // 模拟登录页面 PostMethod post = new PostMethod(login_Action); NameValuePair userName = new NameValuePair("memberName",params[0] ); NameValuePair password = new NameValuePair("password",params[1]...

    HttpClient 4.5 封装的工具类 HttpUtil 可用于爬虫和模拟登陆

    基于Apache HttpClient 4.5.2 封装的工具类 HttpUtil 可用于爬虫和模拟登陆。使用新的语法后比3.*版本的速度感觉有提升。使用后注意资源的释放 pom 部分,应该不全,需要用的根据代码的import去找maven资源即可。 ...

    HttpClient使用示例教程

    HttpClient已经应用在很多的项目中,比如Apache Jakarta上很著名的另外两个开源项目Cactus和HTMLUnit都使用了HttpClient。 适用人群:JavaWeb开发者 使用场景:在Java后端程序中,模拟浏览器端进行Web请求。 其它:...

    HttpClient以及获取页面内容应用

    * post方式提交表单(模拟用户登录请求) */ public void postForm() { // 创建默认的httpClient实例. CloseableHttpClient httpclient = HttpClients.createDefault(); // 创建httppost ...

    org.apache.http的jar包

    Apache 的HTTP客户端开源项目---HttpClient。它完全能够处理HTTP连接中的各种问题,使用起来非常方便。只需在项目中引入 HttpClient.jar 包,就可以模拟 IE 来获取网页内容。

    接口开发、springboot、接口转发、前端直接调用图床API时我们发现会报错,编写一个后端接口进行代理即可解决,已实现的例子

    2. Apache HttpClient库 模拟请求API接口 3. MultipartEntityBuilder 将上传相关参数以这种方式提交给目标API。 4. Jackson库 用于序列化和反序列化JSON数据。 5. Java I/O 基于Java I/O操作 6. UUID类 避免...

    基于Tomcat搭建SSL双向认证示例【100012422】

    Tomcat搭建SSL双向认证Demo、Java原生类库SSLSocket编程、Apache的Httpclient库模拟请求

    java-server:基于HTTP的简单迷你游戏后端

    Apache HttpClient 4.3.4用于在单元测试中模拟客户端。 包括的必要依赖项是: 通用编解码器1.6 commons-logging-1.1.3 fluent-hc-4.3.4 httpclient-4.3.4 httpclient-cache-4.3.4 httpcore-4.3.2 ...

    httpclient:用于 REST 的安卓客户端

    使用的库是 com.google.code.gson:gson:2.2.3 org.apache.httpcomponents.httpclient:4.0 其他库(如 android support 和 httpmime)作为导出库包含在产品中但未使用。 JUnit4 案例正在针对已知的 REST API 测试...

    http.rar_源码

    模拟http请求。使用org.apache.commons.httpclient包。已经过测试

    CDSpace 测试工具

    CDSpace是基于Apache Http Client和Sun Http Server两个库,以JavaFX为GUI框架开发的一款HTTP接口测试工具,主要功能分为两部分:1、模拟HttpClient发送自定义请求给服务端,接受响应并将响应的消息体和头域显示在...

    HTTP接口测试工具-CDSpace

    CDSpace是基于Apache Http Client和Sun Http Server两个库,以JavaFX为GUI框架开发的一款HTTP接口测试工具,主要功能分为两部分:1、模拟HttpClient发送自定义请求给服务端,接受响应并将响应的消息体和头域显示在...

    Android开发案例驱动教程 配套代码

    15.2.3 Apache HttpClient实现方式 378 15.3 数据交换格式 380 15.3.1 纯文本格式 381 15.3.2 XML格式 381 15.3.3 JSON格式 385 15.4 自定义服务器端程序实例 387 15.4.1 Java Servlet概述 387 15.4.2 编写...

    selenium httpunit测试程序

    项目实现了JAVA底层自动打开页面,模拟事件操作,获取源文件整体功能。 继承了httpunit selenium两组插件包。 包含完全源代码和JAVA包。 自己花了20多个积分,东拼西凑,用了一个星期,总算把程序调通。希望后来者...

    低清版 大型门户网站是这样炼成的.pdf

    7.7.1 优秀的模拟浏览器httpclient 514 7.7.2 构建通用静态页面发布引擎 516 7.8 小结 518 第8章 通用新闻采集系统 519 8.1 新闻采集系统需求分析 519 8.2 新闻采集系统功能设计 520 8.3 使用正则表达式与...

    JAVA上百实例源码以及开源项目源代码

    Applet钢琴模拟程序java源码 2个目标文件,提供基本的音乐编辑功能。编辑音乐软件的朋友,这款实例会对你有所帮助。 Calendar万年历 1个目标文件 EJB 模拟银行ATM流程及操作源代码 6个目标文件,EJB来模拟银行ATM...

    JAVA上百实例源码以及开源项目

    6个目标文件,EJB来模拟银行ATM机的流程及操作:获取系统属性,初始化JNDI,取得Home对象的引用,创建EJB对象,并将当前的计数器初始化,调用每一个EJB对象的count()方法,保证Bean正常被激活和钝化,EJB对象是用...

Global site tag (gtag.js) - Google Analytics