JDK1.6使用httpclient调用https接口时跳过证书验证

需求

Java代码基于JDK1.6,需要调用https接口,且contentType类型为MULTIPART_FORM_DATA。

实现

在实现上面的需求时遇到两个问题,找到解决方法费了点时间。
所以在此记录下来,希望给遇到同样问题的同学一点启发。请看第一版代码:

public static void main(String[] args) {
    String url = "https://10.22.1.50:443/workorder/subUrlInterface";
    String param = "value";
    HttpUtils.doPostWithFormData(url, param);
}

public static void doPostWithFormData(String url, String param){
    CloseableHttpClient client = null;
    HttpPost post = buildPost(url, param);

    try {
        client = HttpClients.createDefault();
        HttpResponse response = client.execute(post);

        if(response.getStatusLine().getStatusCode() == 200){
            HttpEntity httpEntity = response.getEntity();
            String responseContent = EntityUtils.toString(httpEntity, "UTF-8");
            System.out.println("response is:" + responseContent);
        }else {
            System.out.println("response code is:" + response.getStatusLine().getStatusCode());
        }
    }catch (Exception e){
        e.printStackTrace();
    }finally {
        try {
            if(client != null){
                client.close();
            }
        }catch (IOException e){
            e.printStackTrace();
        }
    }
}

private static HttpPost buildPost(String url, String param){
    HttpPost post = new HttpPost(url);
    HttpEntity multipart = buildEntity(param);
    post.setEntity(multipart);
    return post;
}

private static HttpEntity buildEntity(String param){
    MultipartEntityBuilder builder = MultipartEntityBuilder.create();
    ContentType type = ContentType.create("multipart/form-data", Charset.forName("UTF-8"));
    builder.addTextBody("data", param, type);
    return builder.build();
}

执行上面代码的错误提示是:

javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: 
	PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: 
		unable to find valid certification path to requested target

在网上搜到的解决方案是:修改CloseableHttpClient的初始化方式。修改后的初始化代码是:

............
// 创建一个不验证证书的 httpClient
client = createHttpClient();
............

private static CloseableHttpClient createHttpClient() throws Exception{
    SSLContext sslcontext = SSLContexts.custom().loadTrustMaterial(null, new TrustStrategy() {
        @Override
        public boolean isTrusted(X509Certificate[] chain, String authType) {
            return true;
        }
    }).build();
    SSLConnectionSocketFactory sslSf = new SSLConnectionSocketFactory(sslcontext, null, null,
            new NoopHostnameVerifier());
    return HttpClients.custom().setSSLSocketFactory(sslSf).build();
}

如果代码是基于JDK1.8的话,那么这个问题就算解决了。但是在JDK1.6中,还是会报错:

javax.net.ssl.SSLException: java.lang.RuntimeException: Could not generate DH keypair

在网上搜到的解决方案是:扩展java.security,引入bcprov-jdk15on-1.60.jar。将下面的这行代码放在发送post请求前。

Security.insertProviderAt(new BouncyCastleProvider(), 1);

至此,调用https接口正常。

依赖

  • httpclient-4.5.10.jar
  • httpcore-4.4.12.jar
  • httpmime-4.5.11.jar
  • bcprov-jdk15on-1.60.jar
  • commons-logging-1.2.jar
  • slf4j-api-1.7.1.jar

请求配置

上面的示例代码中没有体现出发送请求时的配置,如超时时间等。具体配置可参考下面的代码:

private static RequestConfig requestConfig;
static {
    // http 连接配置
    RequestConfig.Builder configBuilder = RequestConfig.custom();
    configBuilder.setConnectTimeout(3000);
    configBuilder.setSocketTimeout(3000);
    configBuilder.setConnectionRequestTimeout(3000);
    configBuilder.setExpectContinueEnabled(true);
    requestConfig = configBuilder.build();
}

............
HttpPost post = new HttpPost(url);
post.setConfig(requestConfig);
............

参考资料:
  1. https://www.javaear.com/question/40381968.html
  2. https://www.cnblogs.com/moy25/p/8658762.html
  3. https://www.jianshu.com/p/d6ab78e4ed73
  4. https://blog.csdn.net/qq441568267/article/details/77715624
  5. https://docs.oracle.com/javase/6/docs/api/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值