尝试使用 Java 连接 https 服务器时抛出 SSLHandshakeException
Throw SSLHandshakeException when try to connect https server using Java
我尝试使用 Java 从“https://api.softtouch.eu/#/xxxxxxxx/#/customers?take=100”检索数据。
我还尝试使用以下选项解决 https 的问题:-
使用 Java keytool
将证书(.pem 扩展文件)添加到密钥库 ($JAVA_HOME/jre/lib/security/cacerts)
使用 update-ca-certificates 命令向 Ubuntu (/usr/local/share/ca-certificates) 添加了证书颁发机构。
最后尝试禁用证书验证并连接到服务器。 (此处为 SoftTouchConnection class 和自定义 TrustAllX509TrustManager class。)
package com.softtouch.com;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.security.Security;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import org.apache.commons.codec.binary.Base64;
public class SoftTouchConnection {
public static void main(String[] args) {
try {
System.out.println(System.getProperty("java.version"));
System.setProperty("javax.net.debug", "ssl");
System.setProperty("sun.net.ssl.checkRevocation", "false");
java.lang.System.setProperty("sun.security.ssl.allowUnsafeRenegotiation", "true");
Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());
SSLContext sc = SSLContext.getInstance("SSL");//TLSv1.2
sc.init(null, new TrustManager[] {new TrustAllX509TrustManager() }, null);//new java.security.SecureRandom()
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String string, SSLSession ssls) {
System.out.println("test HttpsURLConnection");
return true;
}
});
String userCredentialsnew = "abcdefghij01234567890klmnopqrstuvwxyz987";//"bearer abcdefghij01234567890klmnopqrstuvwxyz987";
String basicAuth = "Basic "+ new String(new Base64().encode(userCredentialsnew.getBytes()));; //+ new String(new Base64().encode(userCredentials.getBytes()));
URL hh= new URL("https://api.softtouch.eu/#/xxxxxxxx/#/customers?take=100");
HttpsURLConnection conn = (HttpsURLConnection)hh.openConnection();
conn.setSSLSocketFactory(sc.getSocketFactory());
conn.setHostnameVerifier( new HostnameVerifier() {
@Override
public boolean verify(String string, SSLSession ssls) {
System.out.println("test conn");
return true;
}
});
conn.setDoInput(true);
conn.setDoOutput(false);
conn.setUseCaches(false);
conn.setRequestMethod("GET");
conn.setRequestProperty ("Authorization", basicAuth);
conn.connect();
BufferedReader inn = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String inputLine;
while ((inputLine = inn.readLine()) != null) {
System.out.println(inputLine);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
package com.softtouch.com;
import javax.net.ssl.X509TrustManager;
import java.security.cert.X509Certificate;
public class TrustAllX509TrustManager implements X509TrustManager {
public X509Certificate[] getAcceptedIssuers() {
System.out.println("test1");
//return new X509Certificate[0];
return null;
}
public void checkClientTrusted(java.security.cert.X509Certificate[] certs,String authType) {
System.out.println("test2");
}
public void checkServerTrusted(java.security.cert.X509Certificate[] certs,String authType) {
System.out.println("test3");
}
}
但是到目前为止我还没有解决问题。我收到了"javax.net.ssl.SSLHandshakeException"。
我想使用 Java 连接到服务器。 这个问题的原因是什么?
注意:- 我测试了“https://api.softtouch.eu/#/accounts/#/xxxxxxxx?take=100”与 PHP 的连接。它运作良好。但是 PHP 源文件使用了以下行来禁用 SSL 验证。
curl_setopt($httpRequest, CURLOPT_SSL_VERIFYPEER, 假);
这是 SSL 调试文本:-
*** ClientHello, TLSv1.2
RandomCookie:GMT:1425473345 字节 = { 113、222、27、25、227、136、38、249、128、230、125、228、156、5、175、99、22、55、227、185、101, 32, 160, 186, 72, 167, 247, 166 }
会话 ID:{}
密码套件:[TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256、TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256、TLS_RSA_WITH_AES_128_CBC_SHA256、TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256、TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256、TLS_DHE_RSA_WITH_AES_128_CBC_SHA256、TLS_DHE_DSS_WITH_AES_128_CBC_SHA256、TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, TLS_DHE_DSS_WITH_AES_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_RSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA、TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA、SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA、SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA、TLS_EMPTY_RENEGOTIATION_INFO_SCSV]
压缩方法:{ 0 }
Extension elliptic_curves, curve names: {secp256r1, sect163k1, sect163r2, secp192r1, secp224r1, sect233k1, sect233r1, sect283k1, sect283r1, secp384r1, sect409k1, sect409r1, secp521r1, sect571k1, sect571r1, secp160k1, secp160r1, secp160r2, sect163r1, secp192k1 , sect193r1, sect193r2, secp224k1, sect239k1, secp256k1}
扩展 ec_point_formats,格式:[未压缩]
扩展 signature_algorithms、signature_algorithms:SHA512withECDSA、SHA512withRSA、SHA384withECDSA、SHA384withRSA、SHA256withECDSA、SHA256withRSA、SHA224withECDSA、SHA224withRSA、SHA1withECDSA、SHA1withRSA、SHA1withDSA、MD5withRSA
主要,写入:TLSv1.2 握手,长度 = 195
主要,阅读:TLSv1.2 警报,长度 = 2
主要,RECV TLSv1.2 警报:致命,handshake_failure
主要,称为 closeSocket()
站点的证书没有问题,因此您不需要禁用证书验证。但是,该站点需要使用 Server Name Indication (SNI) 来提供正确的证书。是否支持 SNI 取决于 Java 版本,但它不适用于 Java 1.6 及更低版本。
除此之外,握手异常可能表明该问题与证书验证根本无关。该站点仅支持少数全部使用 AES256 的密码。但由于出口限制,Java 默认不支持 AES256。
我尝试使用 Java 从“https://api.softtouch.eu/#/xxxxxxxx/#/customers?take=100”检索数据。
我还尝试使用以下选项解决 https 的问题:-
使用 Java keytool
将证书(.pem 扩展文件)添加到密钥库 ($JAVA_HOME/jre/lib/security/cacerts)
使用 update-ca-certificates 命令向 Ubuntu (/usr/local/share/ca-certificates) 添加了证书颁发机构。
最后尝试禁用证书验证并连接到服务器。 (此处为 SoftTouchConnection class 和自定义 TrustAllX509TrustManager class。)
package com.softtouch.com; import java.io.BufferedReader; import java.io.InputStreamReader; import java.net.URL; import java.security.Security; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSession; import javax.net.ssl.TrustManager; import org.apache.commons.codec.binary.Base64; public class SoftTouchConnection { public static void main(String[] args) { try { System.out.println(System.getProperty("java.version")); System.setProperty("javax.net.debug", "ssl"); System.setProperty("sun.net.ssl.checkRevocation", "false"); java.lang.System.setProperty("sun.security.ssl.allowUnsafeRenegotiation", "true"); Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider()); SSLContext sc = SSLContext.getInstance("SSL");//TLSv1.2 sc.init(null, new TrustManager[] {new TrustAllX509TrustManager() }, null);//new java.security.SecureRandom() HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() { @Override public boolean verify(String string, SSLSession ssls) { System.out.println("test HttpsURLConnection"); return true; } }); String userCredentialsnew = "abcdefghij01234567890klmnopqrstuvwxyz987";//"bearer abcdefghij01234567890klmnopqrstuvwxyz987"; String basicAuth = "Basic "+ new String(new Base64().encode(userCredentialsnew.getBytes()));; //+ new String(new Base64().encode(userCredentials.getBytes())); URL hh= new URL("https://api.softtouch.eu/#/xxxxxxxx/#/customers?take=100"); HttpsURLConnection conn = (HttpsURLConnection)hh.openConnection(); conn.setSSLSocketFactory(sc.getSocketFactory()); conn.setHostnameVerifier( new HostnameVerifier() { @Override public boolean verify(String string, SSLSession ssls) { System.out.println("test conn"); return true; } }); conn.setDoInput(true); conn.setDoOutput(false); conn.setUseCaches(false); conn.setRequestMethod("GET"); conn.setRequestProperty ("Authorization", basicAuth); conn.connect(); BufferedReader inn = new BufferedReader(new InputStreamReader(conn.getInputStream())); String inputLine; while ((inputLine = inn.readLine()) != null) { System.out.println(inputLine); } } catch (Exception e) { e.printStackTrace(); } } } package com.softtouch.com; import javax.net.ssl.X509TrustManager; import java.security.cert.X509Certificate; public class TrustAllX509TrustManager implements X509TrustManager { public X509Certificate[] getAcceptedIssuers() { System.out.println("test1"); //return new X509Certificate[0]; return null; } public void checkClientTrusted(java.security.cert.X509Certificate[] certs,String authType) { System.out.println("test2"); } public void checkServerTrusted(java.security.cert.X509Certificate[] certs,String authType) { System.out.println("test3"); } }
但是到目前为止我还没有解决问题。我收到了"javax.net.ssl.SSLHandshakeException"。 我想使用 Java 连接到服务器。 这个问题的原因是什么?
注意:- 我测试了“https://api.softtouch.eu/#/accounts/#/xxxxxxxx?take=100”与 PHP 的连接。它运作良好。但是 PHP 源文件使用了以下行来禁用 SSL 验证。 curl_setopt($httpRequest, CURLOPT_SSL_VERIFYPEER, 假);
这是 SSL 调试文本:- *** ClientHello, TLSv1.2 RandomCookie:GMT:1425473345 字节 = { 113、222、27、25、227、136、38、249、128、230、125、228、156、5、175、99、22、55、227、185、101, 32, 160, 186, 72, 167, 247, 166 } 会话 ID:{} 密码套件:[TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256、TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256、TLS_RSA_WITH_AES_128_CBC_SHA256、TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256、TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256、TLS_DHE_RSA_WITH_AES_128_CBC_SHA256、TLS_DHE_DSS_WITH_AES_128_CBC_SHA256、TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, TLS_DHE_DSS_WITH_AES_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_RSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA、TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA、SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA、SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA、TLS_EMPTY_RENEGOTIATION_INFO_SCSV] 压缩方法:{ 0 } Extension elliptic_curves, curve names: {secp256r1, sect163k1, sect163r2, secp192r1, secp224r1, sect233k1, sect233r1, sect283k1, sect283r1, secp384r1, sect409k1, sect409r1, secp521r1, sect571k1, sect571r1, secp160k1, secp160r1, secp160r2, sect163r1, secp192k1 , sect193r1, sect193r2, secp224k1, sect239k1, secp256k1} 扩展 ec_point_formats,格式:[未压缩] 扩展 signature_algorithms、signature_algorithms:SHA512withECDSA、SHA512withRSA、SHA384withECDSA、SHA384withRSA、SHA256withECDSA、SHA256withRSA、SHA224withECDSA、SHA224withRSA、SHA1withECDSA、SHA1withRSA、SHA1withDSA、MD5withRSA
主要,写入:TLSv1.2 握手,长度 = 195 主要,阅读:TLSv1.2 警报,长度 = 2 主要,RECV TLSv1.2 警报:致命,handshake_failure 主要,称为 closeSocket()
站点的证书没有问题,因此您不需要禁用证书验证。但是,该站点需要使用 Server Name Indication (SNI) 来提供正确的证书。是否支持 SNI 取决于 Java 版本,但它不适用于 Java 1.6 及更低版本。
除此之外,握手异常可能表明该问题与证书验证根本无关。该站点仅支持少数全部使用 AES256 的密码。但由于出口限制,Java 默认不支持 AES256。