目录
- 问题解决
- 问题描述
- 问题分析
- 解决过程
@(终于等到你)
问题解决
问题描述
首先,服务器上跑着一个接口工程,环境是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请求证书问题
原文地址:https://www.cnblogs.com/charmsongo/p/9849049.html