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](https://my.oschina.net/u/2303379) url
 * [@param](https://my.oschina.net/u/2303379) timeout 超时时间(毫秒)
 * [@param](https://my.oschina.net/u/2303379) user
 * [@param](https://my.oschina.net/u/2303379) code
 * [@return](https://my.oschina.net/u/556800)
 */
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

转载于:https://my.oschina.net/charmsongo/blog/2252274

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
如果您在不同版本的JDK中运行MapReduce程序,可能会出现以下问题: 1. 编译错误:不同版本的JDK可能会引入不同的API和类库,导致编译错误。 2. 运行错误:由于不同版本的JDK可能会有不同的行为,因此程序在不同版本的JDK中运行时可能会出现错误。 为了避免这些问题,建议您在开发和部署MapReduce程序时使用相同版本的JDK。如果您必须在不同版本的JDK中运行程序,则可以尝试以下方法: 1. 使用向后兼容的API:如果您在较新的JDK中编写程序,可以尝试使用向后兼容的API,以便在较旧的JDK中运行程序。例如,Java 7中引入的try-with-resources语句在Java 6中不可用,但您可以使用传统的try-catch-finally语句来代替。 2. 编译时指定目标JDK版本:您可以使用javac命令的-target选项来指定编译后的类文件应该在哪个JDK版本中运行。例如,您可以使用以下命令将类文件编译为Java 6兼容的格式: javac -target 1.6 MyMapReduce.java 3. 运行时指定JDK版本:如果您在较新的JDK中编译程序,但必须在较旧的JDK中运行程序,则可以尝试使用-javaagent命令行选项来指定在运行时使用的JDK版本。例如,您可以使用以下命令来启动程序并指定在Java 6中运行: java -javaagent:/path/to/jdk6/agent.jar MyMapReduce 请注意,这些方法可能不适用于所有情况,并且可能会导致其他问题。建议您尽可能使用相同版本的JDK来开发和部署MapReduce程序。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值