我正在尝试实现双向(相互)SSL 身份验证,但我在 Glassfish3/4 和 Tomcat 8 服务器上经常遇到以下异常(堆栈跟踪来自 Tomcat 8):
10-Feb-2016 17:13:41.579 SEVERE [http-nio2-18443-exec-2] org.apache.tomcat.util.net.Nio2Endpoint$SocketProcessor.doRun Error running socket processor
java.lang.RuntimeException: Field length overflow, the field length (7189180) should be less than 65536
at sun.security.ssl.Handshaker.checkThrown(Handshaker.java:1373)
at sun.security.ssl.SSLEngineImpl.checkTaskThrown(SSLEngineImpl.java:529)
at sun.security.ssl.SSLEngineImpl.readNetRecord(SSLEngineImpl.java:807)
at sun.security.ssl.SSLEngineImpl.unwrap(SSLEngineImpl.java:775)
at javax.net.ssl.SSLEngine.unwrap(SSLEngine.java:624)
at org.apache.tomcat.util.net.SecureNio2Channel.handshakeUnwrap(SecureNio2Channel.java:394)
at org.apache.tomcat.util.net.SecureNio2Channel.handshakeInternal(SecureNio2Channel.java:267)
at org.apache.tomcat.util.net.SecureNio2Channel.handshake(SecureNio2Channel.java:204)
at org.apache.tomcat.util.net.Nio2Endpoint$SocketProcessor.doRun(Nio2Endpoint.java:1064)
at org.apache.tomcat.util.net.Nio2Endpoint$SocketProcessor.run(Nio2Endpoint.java:1046)
at org.apache.tomcat.util.net.Nio2Endpoint.processSocket0(Nio2Endpoint.java:598)
at org.apache.tomcat.util.net.Nio2Endpoint.processSocket(Nio2Endpoint.java:583)
at org.apache.tomcat.util.net.SecureNio2Channel$1.completed(SecureNio2Channel.java:83)
at org.apache.tomcat.util.net.SecureNio2Channel$1.completed(SecureNio2Channel.java:76)
at sun.nio.ch.Invoker.invokeUnchecked(Invoker.java:126)
at sun.nio.ch.Invoker$2.run(Invoker.java:218)
at sun.nio.ch.AsynchronousChannelGroupImpl$1.run(AsynchronousChannelGroupImpl.java:112)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
经过长时间的搜索,我只发现这个链接显示了同样的问题,但在 JBoss 上。这真的与密钥/信任库中条目的大小/数量有关吗?我现在存储了大约 66.000 个证书,但随着开发的进行,我们预计会更多(例如,数十万个)。
使用几乎空的密钥库(其中只有服务器和一个测试客户端证书),测试 SSL 连接curl
是成功的......
更新
好的,我想我发现它确实与信任库有关。这是来自的代码片段sun.security.ssl.HandshakeMessage.CertificateRequest
:
// put certificate_authorities
int len = 0;
for (int i = 0; i < authorities.length; i++) {
len += authorities[i].length();
}
output.putInt16(len);
该putInt()
方法中触发了异常,因此我认为我确实存储了太多证书。我现在正在生成自签名证书,所以我必须将每个生成的证书作为服务器上的 CA 来信任客户端,这一定是问题所在。现在的问题是,有没有办法从 Java 生成非自签名的证书(例如,我可以使用 glassfish 的自签名证书作为 CA - 或者我可以)?