1. 程式人生 > >JDK版本不同引發的https請求證書問題

JDK版本不同引發的https請求證書問題

ams new t .exe 現實 fig tps hand head ext

目錄

  • 問題解決
    • 問題描述
    • 問題分析
    • 解決過程

@(終於等到你)

問題解決

問題描述

首先,服務器上跑著一個接口工程,環境是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請求證書問題