分享web开发知识

注册/登录|最近发布|今日推荐

主页 IT知识网页技术软件开发前端开发代码编程运营维护技术分享教程案例
当前位置:首页 > 运营维护

记录一次解决httpcline请求https报handshake_failure错误

发布时间:2023-09-06 01:46责任编辑:胡小海关键词:http
概述
当使用httpclinet发起https请求时报如下错误:
javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure ???at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:174) ???at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:136) ???at com.sun.net.ssl.internal.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:1657) ???at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:932) ???at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1096) ???at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1123) ???at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1107) ???at org.apache.http.conn.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.java:261) ???at org.apache.http.impl.conn.HttpClientConnectionOperator.connect(HttpClientConnectionOperator.java:118) ???at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:314) ???at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:357) ???at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:218) ???at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:194) ???at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:85) ???at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:108) ???at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:186) ???at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82) ???at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:106)

未解决参照url

访问https,抛出的异常javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
使用HttpClient发送HTTPS请求以及配置Tomcat支持SSL

分析过程

背景交待

由于证书是字自签自发,并且加固过,相信很多人会问为什么加固, 因为你如果不加固的话https将在ff中无法访问,错误如下:

解决方案参照Tomcat6+JDK6如何加固,解决Logjam attack

解决过程分析

不加固是否可以直接访问

经测试 不加固的情况访问没有问题

加固后不能访问原因分析

因为加固主要是指定了protocols和ciphers,所以请求时是否也可以指定protocols和ciphers,查阅官方文档发现如下信息

通过在httpclient请求之前设置protocols和ciphers,代码如下:

 ???????System.setProperty("https.protocols", "与server.xml中的protocols一致"); ???????System.setProperty("https.cipherSuites", "与server.xml中的ciphers一致");

重新发起请求,发现还是报错

分析设置是否生效

通过debug httpclinet下HttpClientBuilder类的源代码发现如下

则将代码增加如下粗体:
HttpClients.custom().useSystemProperties().setDefaultRequestConfig(defaultRequestConfig).setSslcontext(sslcontext).build();
重新发起请求,发现还是报错

查询本地支持的协议及算法

代码如下:

public class HttpsTest { ???public static void main(String[] args) { ???????SSLContext sc; ???????try { ???????????sc = SSLContext.getInstance("TLS"); ???????????// 实现一个X509TrustManager接口,用于绕过验证,不用修改里面的方法 ???????????X509TrustManager trustManager = new X509TrustManager() { ???????????????@Override ???????????????public void checkClientTrusted( ???????????????????????java.security.cert.X509Certificate[] paramArrayOfX509Certificate, ???????????????????????String paramString) throws CertificateException { ???????????????} ???????????????@Override ???????????????public void checkServerTrusted( ???????????????????????java.security.cert.X509Certificate[] paramArrayOfX509Certificate, ???????????????????????String paramString) throws CertificateException { ???????????????} ???????????????@Override ???????????????public java.security.cert.X509Certificate[] getAcceptedIssuers() { ???????????????????return null; ???????????????} ???????????}; ???????????sc.init(null, new TrustManager[] { trustManager }, null); ???????????System.out.println("缺省安全套接字使用的协议: " + sc.getProtocol()); ?????????????// 获取SSLContext实例相关的SSLEngine ?????????????SSLEngine en = sc.createSSLEngine(); ?????????????System.out ?????????????????????.println("支持的协议: " + Arrays.asList(en.getSupportedProtocols())); ?????????????System.out.println("启用的协议: " + Arrays.asList(en.getEnabledProtocols())); ?????????????System.out.println("支持的加密套件: " ?????????????????????+ Arrays.asList(en.getSupportedCipherSuites())); ?????????????System.out.println("启用的加密套件: " ?????????????????????+ Arrays.asList(en.getEnabledCipherSuites())); ????????} catch (Exception e) { ???????????// TODO Auto-generated catch block ???????????e.printStackTrace(); ???????} ???}}然后在httpclient请求之前设置protocols和ciphers,
 ???System.setProperty("https.protocols", "其值为服务器和本地相同的"); ???System.setProperty("https.cipherSuites", "其值为服务器和本地相同的");

重新发起请求,请求成功。

版本说明

httpclinet:4.3.1
jdk:1.6
tomcat:6

httpclient发起请求代码

访问 https://gitee.com/die/help_common.git中的httpclinet进行下载

参考文章

HttpClient如何指定CipherSuites

记录一次解决httpcline请求https报handshake_failure错误

原文地址:http://blog.51cto.com/2074199/2088928

知识推荐

我的编程学习网——分享web前端后端开发技术知识。 垃圾信息处理邮箱 tousu563@163.com 网站地图
icp备案号 闽ICP备2023006418号-8 不良信息举报平台 互联网安全管理备案 Copyright 2023 www.wodecom.cn All Rights Reserved