最近在生产环境调用Https接口出现这个问题javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure,经查询,见到网上大部分答案是替换%JAVA_HOME%\jre\lib\security路径下的两个jar包,local_policy.jar和US_export_policy.jar,由于自己替换后发现依旧出现了这个问题,最终解决了,于是总结一下自己的解决方法以及出现的问题,调用接口我使用的是jdk自带的类,没有使用第三方包。自己出现的问题如下
一、是使用错误,如下图,调用Https接口,应该使用HttpsURLConnection这个来创建连接,而不是HttpURLConnection,
二、没有设置协议版本,可能使用了默认的版本,Https接口时会进行一个协议版本校验,校验客户端协议的版本和服务端版本是否一致,可以在这个网站查询 https://myssl.com/ 调用地址支持的协议版本,使用的是什么协议,如下图,
然后设置HttpsURLConnection请求时使用的协议,如下图,第一个红框中SLContext.getInstance("TLSv1.2")中的参数TLSv1.2就是为协议版本,应该对应填写服务器端支持的协议版本。
然后提供下完成代码
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import java.io.*;
import java.net.*;
public static String insureResponsePost(String url, String param) {
PrintWriter out = null;
InputStream is = null;
BufferedReader br = null;
String result = "";
HttpsURLConnection conn = null;
StringBuffer strBuffer = new StringBuffer();
try {
// 创建SSLContext
SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
TrustManager[] tm = {new RecX509TrustManager()};
// 初始化
sslContext.init(null, tm, new java.security.SecureRandom());
// 获取SSLSocketFactory对象
SSLSocketFactory ssf = sslContext.getSocketFactory();
URL realUrl= new URL(url);
conn = (HttpsURLConnection) realUrl.openConnection();
// 设置通用的请求属性
conn.setRequestMethod( "POST");
conn.setConnectTimeout(20000);
conn.setReadTimeout(300000);
conn.setRequestProperty("Charset", "UTF-8");
// 传输数据为json,如果为其他格式可以进行修改
conn.setRequestProperty( "Content-Type", "application/json; charset=utf-8");
// 发送POST请求必须设置如下两行
conn.setDoOutput( true);
conn.setDoInput( true);
conn.setUseCaches( false);
conn.setSSLSocketFactory(ssf);
// 获取URLConnection对象对应的输出流
out = new PrintWriter(conn.getOutputStream());
// 发送请求参数
log.info(url+"post请求数据"+param);
out.print(param);
// flush输出流的缓冲s
out.flush();
is = conn.getInputStream();
br = new BufferedReader( new InputStreamReader(is));
String line = null;
while ((line=br.readLine())!= null) {
strBuffer.append(line);
}
result = strBuffer.toString();
log.info("响应结果"+result);
} catch (Exception e) {
log.info("请求异常",e);
}
// 使用finally块来关闭输出流、输入流
finally {
try {
if (out != null) {
out.close();
}
if (br != null) {
br.close();
}
if (conn!= null) {
conn.disconnect();
}
} catch (IOException ex) {
log.info("调用异常",ex);
}
}
log.info(url+"post请求响应结果"+result);
return result;
}
网上有其他的解决方法,有的是这样设置System.setProperty(“https.protocols”, “TLSv1.2,TLSv1.1,SSLv3”),这种个人感觉还是不太好,这个像是全文设置,可能会影响别的地方,希望能给你提供帮助。