記錄一次解決httpcline請求https報handshake_failure錯誤
阿新 • • 發佈:2018-03-20
HttpClient如何指定Ciphe handshake_failure SSL_ERROR_WEAK_SER httpclinet發起https請求 概述
通過在httpclient請求之前設置protocols和ciphers,代碼如下: .setDefaultRequestConfig(defaultRequestConfig).setSslcontext(sslcontext).build();
重新發起請求,發現還是報錯
當使用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()
重新發起請求,發現還是報錯
查詢本地支持的協議及算法
代碼如下:
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錯誤