[英]Java - Ssl stream is cancelled when using client certificate authentication
I cannot figure this one out. 我无法想出这个。
I have a unit test that performs a connection to my service using a client certificate authentication. 我有一个单元测试,使用客户端证书身份验证执行与我的服务的连接。
// generate a valid client cert and store it in a keystore
String keystorePassword = "xxx";
InputStream pkcs12 = UnitTests.generatePkcs12ForUser(user, keystorePassword, 3600);
KeyStore ks = KeyStore.getInstance("pkcs12");
ks.load(pkcs12, keystorePassword.toCharArray());
String url = getBaseServerUrl();
// prepare a ssl context that has the keystore with client cert and key
SSLContext sslContext = SSLContexts.custom()
.loadKeyMaterial(ks, keystorePassword.toCharArray())
// trust all SSL certs
.loadTrustMaterial((X509Certificate[] chain, String authType) -> true)
.build();
// validate any hostname, and don't follow 3XX responses
HttpClient httpClient = HttpClients.custom()
.setSSLContext(sslContext)
.setSSLHostnameVerifier((a,b) -> true)
.disableRedirectHandling()
.build();
// this fails catastrophically
HttpResponse response = httpClient.execute(new HttpGet(url));
I'm using Java 8 and my server is behind a reverse proxy that uses Nginx. 我使用的是Java 8,而我的服务器是使用Nginx的反向代理。
My unit test fails with an exception like this: 我的单元测试失败,出现如下异常:
javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1002)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1385)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1413)
[...]
Caused by: java.io.EOFException: SSL peer shut down incorrectly
at sun.security.ssl.InputRecord.read(InputRecord.java:505)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:983)
... 43 more
And I can see in the Nginx error.log the following line: 我可以在Nginx error.log中看到以下行:
2018/05/18 15:34:12 [crit] 42#42: *327 SSL_do_handshake() failed (SSL: error:0D0680A8:asn1 encoding routines:asn1_check_tlen:wrong tag error:0D08303A:asn1 encoding routines:asn1_template_noexp_d2i:nested asn1 error) while SSL handshaking, client: 172.18.0.1, server: 0.0.0.0:443
I have SCOURGED the internet to find the reason for this error, and I feel like I have exhausted all recourse. 我已经SCOURGED互联网找到了这个错误的原因,我觉得我已经筋疲力尽了所有的追索权。
Non exhaustive list of things I have tried: 我尝试过的非详尽列表:
-Dhttps.protocols=Tlsv1.1
-> still fails 强制java使用TlsV1.1和-Dhttps.protocols=Tlsv1.1
- >仍然失败 loadTrustMaterial
to always use my own key -> still fails 试图为loadTrustMaterial
指定“关键策略”以始终使用我自己的密钥 - >仍然失败 curl
ed the same address -> it works ?! ...在调试器中将密钥和证书转储到几个PEM文件中并且curl
相同的地址 - >它有效吗? curl -k <url>
above which works flawlessly): 将它与工作样本(上面简单的curl -k <url>
完美无瑕地工作)进行比较:
Do you guys have any idea? 你们有什么想法吗? I'm starting to get crazy. 我开始变得疯狂。 I have a hunch that I'm not setting my connection correctly, but I can't see where. 我有预感,我没有正确设置我的连接,但我看不到在哪里。
For those that didn't read the comments: I figured it out: I was using the subjectAltName as a storage for something that isn't an alternative name. 对于那些没有阅读评论的人:我想通了:我使用subjectAltName作为存储而不是替代名称。
It seems that Java is not happy with this and refuses the connection. 似乎Java对此不满意并拒绝连接。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.