Java 1.7.0_80调用UPS接口报handshake_failure握手异常解决方案求问
解决方案
问题根因
JDK 1.7.0_80 原生仅支持CBC模式的AES、3DES、RC4类加密套件,UPS新服务端已完全废弃上述不安全套件,仅支持GCM模式的AES加密套件(如TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256),JDK1.7原生无对应实现,因此握手直接失败,单纯替换JCE策略包、引入BouncyCastle但未替换SSL层实现无法解决问题。
可行解决方式
方案1:使用兼容JDK1.7的OkHttp版本发送请求(代码改动最小)
OkHttp 3.12.x是最后兼容JDK1.7的版本,内置独立的TLS实现,默认支持GCM类加密套件,无需依赖JDK原生加密能力,替换HTTP调用组件即可解决问题。
示例代码:
// 引入okhttp 3.12.13版本依赖 OkHttpClient client = new OkHttpClient(); RequestBody body = RequestBody.create(MediaType.parse("application/xml; charset=utf-8"), xmlInputString); Request request = new Request.Builder() .url("https://onlinetools.ups.com/......") .post(body) .build(); try (Response response = client.newCall(request).execute()) { String respStr = response.body().string(); System.out.println("response is :" + respStr); } catch (IOException e) { e.printStackTrace(); }
方案2:使用反向代理中转请求(无业务代码改动)
在业务服务所在服务器部署轻量反向代理(如Nginx、Caddy),配置规则:
- 业务服务调用本地代理的HTTP接口,代理接收请求后转发至UPS官方接口
- 代理侧配置支持最新TLS版本及加密套件,和UPS服务端完成握手
该方案完全不需要修改业务代码,仅需要新增代理配置即可。
方案3:Apache HttpClient + BouncyCastle替换原生SSL实现
如果只能用Apache HttpClient组件,可以引入BouncyCastle的TLS实现,替换默认的SSLContext:
// 引入bcpkix-jdk15on、bcprov-jdk15on 1.70版本依赖 Security.addProvider(new BouncyCastleProvider()); SSLContext sslContext = SSLContext.getInstance("TLSv1.2", "BC"); sslContext.init(null, null, new SecureRandom()); CloseableHttpClient client = HttpClients.custom() .setSSLContext(sslContext) .build(); HttpPost post = new HttpPost("https://onlinetools.ups.com/......"); post.setEntity(new StringEntity(xmlInputString, ContentType.APPLICATION_XML)); try (CloseableHttpResponse response = client.execute(post)) { String respStr = EntityUtils.toString(response.getEntity()); System.out.println("response is :" + respStr); } catch (IOException e) { e.printStackTrace(); }
内容的提问来源于stack exchange,提问作者Abhiram Tilak Veerapaneni
相关产品推荐
相关产品推荐

