JDK版本不同引發的https請求證書問題
阿新 • • 發佈:2018-10-25
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版本
解決過程
這裏有兩種解決辦法
- 客戶端升級為jdk8(讓客戶改不怎麽現實,這種方法先pass)
- 構造證書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請求證書問題