JDK版本不同引发的https请求证书问题

Posted charmsongo

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JDK版本不同引发的https请求证书问题相关的知识,希望对你有一定的参考价值。

目录

@(终于等到你)

问题解决

问题描述

首先,服务器上跑着一个接口工程,环境是jdk8,为https请求(证书认证,但这里绕过了证书);客户端通过https调用接口,环境是jdk7,请求时报如下错:

javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure

问题分析

这个问题出现的原因是因为开发时,我客户端用的jdk8测试,没有出现问题,然后客户那是jdk7,所以出现了这个问题,这是由于客户端与服务器所使用的SSL/TLS版本不一致。服务器使用的TLS版本高,而客户端支持的TLS版本低。Java 8默认支持TLSv1.2版本

解决过程

这里有两种解决办法

  1. 客户端升级为jdk8(让客户改不怎么现实,这种方法先pass)
  2. 构造证书new SSLConnectionSocketFactory对象时加上两个属性

这里说下第二种解决方法,下面 SSLConnectionSocketFactory 上的注释
get请求

/**
 * get请求
 * @param url
 * @param timeout 超时时间(毫秒)
 * @param user
 * @param code
 * @return
 */
public static String doGet(String url, int timeout, String user, String code) {
    try {
        CloseableHttpClient client = null;

        /* 相信自己的CA和所有自签名的证书 */
        SSLContext sslcontext = SSLContexts.custom().loadTrustMaterial(new TrustSelfSignedStrategy()).build();

        /* 不做证书校验 */
        sslcontext.init(null, new TrustManager[] { truseAllManager }, null);

        /* 添加两个属性 new String[]{"TLSv1.2"} 和 null */
        SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext,new String[]{"TLSv1.2"}, null, new HostnameVerifier() {
            @Override
            public boolean verify(String hostname, SSLSession session) {
                return true;
            }
        });
        
        client = HttpClients.custom().setSSLSocketFactory(sslsf).build();

        //发送get请求
        HttpGet request = new HttpGet(url);
        request.setHeader("Content-Type", "application/json;charset=UTF-8");
        request.setHeader("User", user);
        request.setHeader("Code", code);
        RequestConfig requestConfig = RequestConfig.custom()
                .setConnectTimeout(timeout)
                .setSocketTimeout(timeout).build();
        request.setConfig(requestConfig);
        HttpResponse response = client.execute(request);

        /**读取服务器返回过来的json字符串数据**/
        String strResult = EntityUtils.toString(response.getEntity());
        return strResult;
    }catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}

post请求

/**
 * post请求(用于请求json格式的参数)
 * @param url 请求路径
 * @param params 请求参数
 * @param user 用户
 * @param code 秘钥
 * @return
 * @throws Exception
 */
public static String doPost(String url, String params, String user, String code) throws Exception {

    CloseableHttpClient httpclient = null;

    /* 相信自己的CA和所有自签名的证书 */
    SSLContext sslcontext = SSLContexts.custom().loadTrustMaterial(new TrustSelfSignedStrategy()).build();

    /* 不做证书校验 */
    sslcontext.init(null, new TrustManager[] { truseAllManager }, null);
    
    /* 添加两个属性 new String[]{"TLSv1.2"} 和 null */
    SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext,new String[]{"TLSv1.2"}, null, new HostnameVerifier() {
        @Override
        public boolean verify(String hostname, SSLSession session) {
            return true;
        }
    });

    httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
    HttpPost httpPost = new HttpPost(url);// 创建httpPost
    httpPost.setHeader("Content-Type", "application/json;charset=UTF-8");
    httpPost.setHeader("User", user);
    httpPost.setHeader("Code", code);
    String charSet = "UTF-8";
    StringEntity entity = new StringEntity(params, charSet);
    httpPost.setEntity(entity);
    CloseableHttpResponse response = null;
    try {

        response = httpclient.execute(httpPost);
            HttpEntity responseEntity = response.getEntity();
            String jsonString = EntityUtils.toString(responseEntity);
            return jsonString;
    }
    finally {
        if (response != null) {
            try {
                response.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        try {
            httpclient.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

具体代码请到 github 自行下载

如果这里不能解决您的问题请参考如下链接

链接1链接2


以上是关于JDK版本不同引发的https请求证书问题的主要内容,如果未能解决你的问题,请参考以下文章

https 请求webServic 产生的安全证书问题 jdk版本导致的Received fatal alert: protocol_version异常

在 java 中验证证书会引发异常 - 无法找到请求目标的有效证书路径

c# https请求忽略证书验证_各种编程语言忽略http的SSL证书认证

jdk生成https证书

使用证书连接时 WCF 请求引发错误

tomcat与https结合