我遇到授权SSL连接的问题。我创建了Struts Action,它通过Client Authorized SSL证书连接到外部服务器。在我的行动中,我试图将一些数据发送到银行服务器,但没有任何运气,因为我从服务器得到以下错误:
error: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
我的Action类从我的Action类发送数据到服务器
//Getting external IP from host
URL whatismyip = new URL("http://automation.whatismyip.com/n09230945.asp");
BufferedReader inIP = new BufferedReader(new InputStreamReader(whatismyip.openStream()));
String IPStr = inIP.readLine(); //IP as a String
Merchant merchant;
System.out.println("amount: " + amount + ", currency: " + currency + ", clientIp: " + IPStr + ", description: " + description);
try {
merchant = new Merchant(context.getRealPath("/") + "merchant.properties");
} catch (ConfigurationException e) {
Logger.getLogger(HomeAction.class.getName()).log(Level.INFO, "message", e);
System.err.println("error: " + e.getMessage());
return ERROR;
}
String result = merchant.sendTransData(amount, currency, IPStr, description);
System.out.println("result: " + result);
return SUCCESS;
我的merchant.properties文件:
bank.server.url=https://-servernameandport-/
https.cipher=-cipher-
keystore.file=-key-.jks
keystore.type=JKS
keystore.password=-password-
ecomm.server.version=2.0
encoding.source=UTF-8
encoding.native=UTF-8
我第一次认为这是证书问题,我将它从.pfx转换为.jks,但我有相同的错误,没有任何更改。
答案 0 :(得分:218)
答案 1 :(得分:19)
答案 2 :(得分:15)
当客户端需要提供证书时,也会发生这种情况。服务器列出证书链后,可能会发生以下情况:
第3。证书申请 服务器将从客户端发出证书请求。该请求将列出服务器接受的所有证书。
*** CertificateRequest
Cert Types: RSA
Cert Authorities:
<CN=blah, OU=blah, O=blah, L=blah, ST=blah, C=blah>
<CN=yadda, DC=yadda, DC=yadda>
<CN=moreblah, OU=moreblah, O=moreblah, C=moreblah>
<CN=moreyada, OU=moreyada, O=moreyada, C=moreyada>
... the rest of the request
*** ServerHelloDone
<强> 4。客户证书链 这是客户端发送到服务器的证书。
*** Certificate chain
chain [0] = [
[
Version: V3
Subject: EMAILADDRESS=client's email, CN=client, OU=client's ou, O=client's Org, L=client's location, ST=client's state, C=client's Country
Signature Algorithm: SHA1withRSA, OID = 1.2.840.113549.1.1.5
... the rest of the certificate
*** ClientKeyExchange, RSA PreMasterSecret, TLSv1
... key exchange info
如果链中没有证书且服务器需要证书,那么您将在此处获得握手错误。可能的原因是找不到证书的路径。
<强> 5。证书验证 客户端要求服务器验证证书
*** CertificateVerify
... payload of verify check
只有在您发送证书时才会执行此步骤。
<强> 6。完成强> 服务器将以验证响应进行响应
*** Finished
verify_data: { 345, ... }
答案 3 :(得分:15)
我不认为这可以解决第一个提问者的问题,但是对于谷歌来这里寻求答案:
在更新51上,默认情况下java 1.8禁止[1] RC4密码,我们可以在发行说明页面上看到:
错误修复:禁止RC4密码套件
RC4现在被视为受损密码。
已从Oracle JSSE实施中的客户端和服务器默认启用的密码套件列表中删除了RC4密码套件。这些密码套件仍然可以通过
SSLEngine.setEnabledCipherSuites()
和SSLSocket.setEnabledCipherSuites()
方法启用。请参阅JDK-8077109(非公开)。
如果您的服务器对此密码具有强烈的偏好(或仅使用此密码),则可以在java上触发handshake_failure
。
您可以测试连接到启用RC4密码的服务器(首先,尝试不使用enabled
参数来查看是否触发handshake_failure
,然后设置enabled
:
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import java.io.*;
import java.util.Arrays;
/** Establish a SSL connection to a host and port, writes a byte and
* prints the response. See
* http://confluence.atlassian.com/display/JIRA/Connecting+to+SSL+services
*/
public class SSLRC4Poke {
public static void main(String[] args) {
String[] cyphers;
if (args.length < 2) {
System.out.println("Usage: "+SSLRC4Poke.class.getName()+" <host> <port> enable");
System.exit(1);
}
try {
SSLSocketFactory sslsocketfactory = (SSLSocketFactory) SSLSocketFactory.getDefault();
SSLSocket sslsocket = (SSLSocket) sslsocketfactory.createSocket(args[0], Integer.parseInt(args[1]));
cyphers = sslsocketfactory.getSupportedCipherSuites();
if (args.length ==3){
sslsocket.setEnabledCipherSuites(new String[]{
"SSL_DH_anon_EXPORT_WITH_RC4_40_MD5",
"SSL_DH_anon_WITH_RC4_128_MD5",
"SSL_RSA_EXPORT_WITH_RC4_40_MD5",
"SSL_RSA_WITH_RC4_128_MD5",
"SSL_RSA_WITH_RC4_128_SHA",
"TLS_ECDHE_ECDSA_WITH_RC4_128_SHA",
"TLS_ECDHE_RSA_WITH_RC4_128_SHA",
"TLS_ECDH_ECDSA_WITH_RC4_128_SHA",
"TLS_ECDH_RSA_WITH_RC4_128_SHA",
"TLS_ECDH_anon_WITH_RC4_128_SHA",
"TLS_KRB5_EXPORT_WITH_RC4_40_MD5",
"TLS_KRB5_EXPORT_WITH_RC4_40_SHA",
"TLS_KRB5_WITH_RC4_128_MD5",
"TLS_KRB5_WITH_RC4_128_SHA"
});
}
InputStream in = sslsocket.getInputStream();
OutputStream out = sslsocket.getOutputStream();
// Write a test byte to get a reaction :)
out.write(1);
while (in.available() > 0) {
System.out.print(in.read());
}
System.out.println("Successfully connected");
} catch (Exception exception) {
exception.printStackTrace();
}
}
}
1 - https://www.java.com/en/download/faq/release_changes.xml
答案 4 :(得分:11)
握手失败可能是一个错误的TLSv1协议实现。
在我们的案例中,这有助于java 7:
File dest = new File(Environment.getExternalStorageDirectory() + "/NewFolder");
dest.mkdirs();
jvm将按此顺序进行协商。具有最新更新的服务器将执行1.2,有缺陷的服务器将下载到v1,并且与java 7中的类似v1一起使用。
答案 5 :(得分:8)
我尝试使用JDK 1.7时遇到此错误。 当我将JDK升级到jdk1.8.0_66时,一切正常。
因此,针对此问题的最简单的解决方案可能是 - 升级您的JDK ,它可以开始运作良好。
答案 6 :(得分:3)
假设您正在使用正确的SSL / TLS协议,正确配置了keyStore
和trustStore
,并确认证书本身不存在任何问题,您可能需要{ {3}}
如strengthen your security algorithms中所述,您收到此错误的一个可能原因是由于使用了不兼容的密码套件。通过使用Vineet's answer中提供的local_policy
文件夹更新我的JDK US_export_policy
文件夹中的security
和textfield
个jar,我就能够成功完成握手。
答案 7 :(得分:3)
就我而言,证书已导入,错误仍然存在,可以通过在连接之前添加using(SqlDataReader reader = _oCmd.ExecuteReader())
{
DataTable dataTable = new DataTable();
dataTable.Load(reader);
objLMT = ConvertTo<LMTUsage>(dataTable);
}
来解决此问题
答案 8 :(得分:2)
我今天遇到了与OkHttp客户端相同的问题来获取基于https的网址。由于Https协议版本和服务器端与客户端之间的密码方法不匹配而导致 。
1)检查您的网站https协议版本和Cipher方法。 openssl>s_client -connect your_website.com:443 -showcerts
您将获得许多详细信息,关键信息如下所示:
SSL-Session:
Protocol : TLSv1
Cipher : RC4-SHA
2)配置您的http客户端,例如,在OkHttp client情况下:
@Test()
public void testHttpsByOkHttp() {
ConnectionSpec spec = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
.tlsVersions(TlsVersion.TLS_1_0) //protocol version
.cipherSuites(
CipherSuite.TLS_RSA_WITH_RC4_128_SHA, //cipher method
CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256)
.build();
OkHttpClient client = new OkHttpClient();
client.setConnectionSpecs(Collections.singletonList(spec));
Request request = new Request.Builder().url("https://your_website.com/").build();
try {
Response response = client.newCall(request).execute();
if(response.isSuccessful()){
logger.debug("result= {}", response.body().string());
}
} catch (IOException e) {
e.printStackTrace();
}
}
这将得到我们想要的。
答案 9 :(得分:2)
如果我的Java客户端进程配置了
,我发现HTTPS服务器以这种方式失败-Djsse.enableSNIExtension=false
handshake_failure
成功完成后但数据流开始之前,ServerHello
连接失败。
没有明确的错误消息确定问题,错误看起来像
main, READ: TLSv1.2 Alert, length = 2
main, RECV TLSv1.2 ALERT: fatal, handshake_failure
%% Invalidated: [Session-3, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384]
main, called closeSocket()
main, handling exception: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
我尝试使用和不使用“-Djsse.enableSNIExtension=false
”选项
答案 10 :(得分:1)
我是TLS
版本不兼容的错误。
以前是TLSv1
我更改了它TLSV1.2
这解决了我的问题。
答案 11 :(得分:1)
我正在使用com.google.api http客户端。当我与内部公司站点进行通信时,当我错误地使用https而不是http时,我遇到了这个问题。
{{1}}
答案 12 :(得分:1)
我有类似的问题;升级到Apache HTTPClient 4.5.3修复它。
答案 13 :(得分:1)
哎呀!对我来说,这简直就是Java版本的问题。我在使用JRE 1.6时遇到握手错误,并且在使用JRE 1.8.0_144时一切正常。
答案 14 :(得分:0)
免责声明:我不知道答案是否会对很多人有所帮助,只是因为它可能会分享。
使用Parasoft SOATest发送请求XML(SOAP)时出现此错误。
问题是,在添加证书并对其进行身份验证后,我从下拉列表中选择了错误的别名。
答案 15 :(得分:0)
就我而言,该网站只能使用TLSv1.2。我使用的是Apache httpclient 4.5.6,我使用以下代码并安装jce来解决此问题(JDK1.7):
jce
jdk7 http://www.oracle.com/technetwork/java/javase/downloads/jce-7-download-432124.html
jdk 8 http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html
代码:
SSLContext sslContext = SSLContext.getDefault();
SSLConnectionSocketFactory sslConnectionFactory = new SSLConnectionSocketFactory(
sslContext,
new String[]{"TLSv1.2"}, // important
null,
NoopHostnameVerifier.INSTANCE);
Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
.register("https", sslConnectionFactory)
.register("http", PlainConnectionSocketFactory.INSTANCE)
.build();
HttpClientConnectionManager ccm = new BasicHttpClientConnectionManager(registry);
httpclient = HttpClientBuilder.create().
.setSSLSocketFactory(sslConnectionFactory)
.setConnectionManager(ccm)
.build();
答案 16 :(得分:0)
要从开发人员(项目1)和系统管理员(项目2和3)的角度进行故障排除:
> as.tibble(cbind(df, binconf(df$count, df$n)))
# A tibble: 6 x 6
id count n PointEst Lower Upper
<dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 1 4 22 0.182 0.0731 0.385
2 2 1 65 0.0154 0.000789 0.0821
3 3 22 34 0.647 0.479 0.785
4 4 4545 6323 0.719 0.708 0.730
5 5 33 35 0.943 0.814 0.984
6 6 23 45 0.511 0.370 0.650
在Java上启用SSL握手调试。-Djavax.net.debug=ssl:handshake:verbose
,则通过sudo apt install ssldump
在服务器上安装ssldump或通过遵循此link从源代码进行编译。Unknown value
ssldump日志无法正常握手的示例:
sudo ssldump -k <your-private-key> -i <your-network-interface>
ssldump日志成功握手的示例
New TCP connection #1: 10.1.68.86(45308) <-> 10.1.68.83(5671)
1 1 0.0111 (0.0111) C>S Handshake
ClientHello
Version 3.3
cipher suites
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
TLS_RSA_WITH_AES_256_GCM_SHA384
TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384
TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384
TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
TLS_DHE_DSS_WITH_AES_256_GCM_SHA384
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_AES_256_CBC_SHA384
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
TLS_RSA_WITH_AES_256_CBC_SHA256
TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384
TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384
TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
TLS_DHE_DSS_WITH_AES_256_CBC_SHA256
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
TLS_RSA_WITH_AES_256_CBC_SHA
TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
TLS_ECDH_RSA_WITH_AES_256_CBC_SHA
TLS_DHE_RSA_WITH_AES_256_CBC_SHA
TLS_DHE_DSS_WITH_AES_256_CBC_SHA
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_EMPTY_RENEGOTIATION_INFO_SCSV
compression methods
NULL
1 2 0.0122 (0.0011) S>C Alert
level fatal
value insufficient_security
1 0.0126 (0.0004) S>C TCP RST
无法正常运行Java日志的示例
New TCP connection #1: 10.1.68.86(56558) <-> 10.1.68.83(8443)
1 1 0.0009 (0.0009) C>S Handshake
ClientHello
Version 3.3
cipher suites
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
Unknown value 0xcca9
Unknown value 0xcca8
Unknown value 0xccaa
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
TLS_DHE_RSA_WITH_AES_256_CBC_SHA
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
TLS_DHE_RSA_WITH_AES_128_CBC_SHA
TLS_RSA_WITH_AES_256_GCM_SHA384
TLS_RSA_WITH_AES_128_GCM_SHA256
TLS_RSA_WITH_AES_256_CBC_SHA256
TLS_RSA_WITH_AES_128_CBC_SHA256
TLS_RSA_WITH_AES_256_CBC_SHA
TLS_RSA_WITH_AES_128_CBC_SHA
TLS_EMPTY_RENEGOTIATION_INFO_SCSV
compression methods
NULL
1 2 0.0115 (0.0106) S>C Handshake
ServerHello
Version 3.3
session_id[0]=
cipherSuite TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
compressionMethod NULL
1 3 0.0115 (0.0000) S>C Handshake
Certificate
1 4 0.0115 (0.0000) S>C Handshake
ServerKeyExchange
Not enough data. Found 294 bytes (expecting 32767)
1 5 0.0115 (0.0000) S>C Handshake
ServerHelloDone
1 6 0.0141 (0.0025) C>S Handshake
ClientKeyExchange
Not enough data. Found 31 bytes (expecting 16384)
1 7 0.0141 (0.0000) C>S ChangeCipherSpec
1 8 0.0141 (0.0000) C>S Handshake
1 9 0.0149 (0.0008) S>C Handshake
1 10 0.0149 (0.0000) S>C ChangeCipherSpec
1 11 0.0149 (0.0000) S>C Handshake
答案 17 :(得分:0)
就我而言,我的1.1版存在一个问题。我很容易用curl重现问题。该服务器不支持低于TLS1.2的版本。
这收到了握手问题:
curl --insecure --tlsv1.1 -i https://youhost --noproxy "*"
在1.2版中,它运行良好:
curl --insecure --tlsv1.2 -i https://youhost --noproxy "*"
服务器正在运行Weblogic,并且在setEnvDomain.sh中添加此参数使其可以与TLSv1.1一起使用:
-Dweblogic.security.SSL.minimumProtocolVersion=TLSv1.1
答案 18 :(得分:0)
由于Java版本而发生此问题。我正在使用1.8.0.231 JDK并收到此错误。我已经将Java版本从1.8.0.231降级到1.8.0.171,现在可以正常使用了。