当前位置: 移动技术网 > IT编程>开发语言>Java > 那些年用httpclient时踩过的一些坑

那些年用httpclient时踩过的一些坑

2019年07月19日  | 移动技术网IT编程  | 我要评论
一、前言 httpclient是java开发中最常用的工具之一,通常大家会使用其中比较基础的api去调用远程。长期开发爬虫,会接触httpclient不常用的api,

一、前言

httpclient是java开发中最常用的工具之一,通常大家会使用其中比较基础的api去调用远程。长期开发爬虫,会接触httpclient不常用的api,同时会遇到各式各样的坑,本文将总结这些年遇到的坑及相应的解决方案。

二、问题及解决方案

问题1:received fatal alert: handshake_failure

问题背景

开发某省份移动爬虫时,加载首页会报标题错误,尝试各种办法都不好使,后来发现换了jdk1.8就可以了。经过长达一个星期源码探寻,发现错误源头是http在握手时,加密算法不支持。

jdk1.8以下版本不支持256位(tls_dhe_rsa_with_aes_256_cbc_sha )

解决方案

1、下载jce扩展包 http://www.oracle.com/technetwork/cn/java/javase/downloads/jce-7-download-432124.html

2、替换/jre/lib/security/里面的两个jar

3、覆盖后如果报错the jurisdiction policy files are not signed by a trusted signer!,说明下载的版本不对,要下对应jdk版本的。

问题2:certificates does not conformto algorithm constraints

问题背景

用mvn打包时报错, security.cert.certificateexception: certificates does not conform toalgorithm constraints

原因是在java1.6之后的这个配置文件中,认为md2的加密方式安全性太低,因而不支持这种加密方式,同时也不支持rsa长度小于1024的密文。

需要修改 java_home/jre/lib/security/java.security #jdk.certpath.disabledalgorithms=md2, rsa keysize < 1024

但是这样做需要把每台机器都改一遍,如果新加机器忘记改了,就会继续报错。因此需要一套方法,只在代码层解决问题。

解决方案

经查源码发现了触发问题的代码位置,通过强制继承sslcontextbuilder,并强制把private的keymanagers和trustmanagers的值置空就可以解决这个问题了。

代码如下:

static class mysslcontextbuilder extends sslcontextbuilder {
 static final string tls = "tls";
 static final string ssl = "ssl";
 private string protocol;
 private set keymanagers;
 private set trustmanagers;
 private securerandom securerandom;
 public mysslcontextbuilder() {
  super();
  this.keymanagers = new hashset();
  this.trustmanagers = new hashset();
 }
}

问题3:超时时间不生效

问题背景

很多人在使用httpclient时会到网上去找例子,例子中经常会有类似这样的设置

httpget.getparams().setparameter(clientpnames.handle_redirects, !isautorelocal);

使用上述方法发送httpclient,在读取配置时,如果发现getparams不为空,则会使得以前设置的所有参数都失效,而使用这里设置的,结果是导致超时时间失效。

解决方案

request.getparams().setparameter是过期方法,其中每一项参数在requestconfig里都有对应的,遍历出来替换一遍即可。

boolean isredirect = true;
  if(request != null) {
   httpparams params = request.getparams();
   if (params instanceof httpparamsnames) {
    // 暂时只支持这个类型
    isredirect = params.getbooleanparameter(
      clientpnames.handle_redirects, true);
   }
   // 清空request
   request.setparams(new basichttpparams());
  }
  if(timeout > 0) {
   builder = requestconfig.custom().setconnectionrequesttimeout(timeout).setconnecttimeout(timeout).setsockettimeout(timeout).setredirectsenabled(isredirect).setcookiespec(cookiespecs.best_match);
  } else {
   builder = requestconfig.custom().setconnectionrequesttimeout(connectiontimeout).setconnecttimeout(connectiontimeout).setredirectsenabled(isredirect).setsockettimeout(sockettimeout).setcookiespec(cookiespecs.best_match);
  }

问题4:fildder监听问题

问题背景

开发爬虫经常会使用fildder来监控网络请求,但是使用httpclient时想用fildder会很难,网上查各种办法都不好用。

下面为大家来排个错,使用下面方法就可以完美解决这个问题,让fildder监控更容易。

解决方案

首先java端

// client builder
httpclientbuilder builder = httpclients.custom();
if(usefidder) {
   // 默认fidder写死
   builder.setproxy(new httphost("127.0.0.1", 8888));
}

fildder端

tools->fiddler options->https->actions->export root certificate to ... \bin\keytool.exe -import -file c:\users\\desktop\fiddlerroot.cer -keystore fiddlerkeystore -alias fiddler

问题5:支持gzip

问题及解决方案

有些网站返回进行了gzip压缩,返回内容是压缩的结果,需要解压。

代码如下:

httpclient wrappedhttpclient = builder.setuseragent(requestua)
    .addinterceptorlast(new httpresponseinterceptor() {
     @override
     public void process(httpresponse httpresponse, httpcontext httpcontext) throws httpexception, ioexception {
      httpentity httpentity = httpresponse.getentity();
      header header = httpentity.getcontentencoding();
      if (header != null) {
       for (headerelement element : header.getelements()) {
        if ("gzip".equalsignorecase(element.getname())) {
         httpresponse.setentity(new gzipdecompressingentity(httpresponse.getentity()));
        }
       }
      }
     }
    })

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对移动技术网的支持。

如您对本文有疑问或者有任何想说的,请点击进行留言回复,万千网友为您解惑!

相关文章:

验证码:
移动技术网