我有一个独立的Java Server Socket application
作为Windows服务在Java 1.8.40上运行,我们有一个Spring Web应用程序作为Client,它使用selfsigned SHA1 RSA 2048
证书和Server Socket application
执行SSL握手,然后执行其他动作。我们在selfsigned SHA1 RSA 2048
keystore.jks中拥有相同的Server Socket application
证书。
我在生产环境中看到Server Socket application
出现了一个奇怪的问题,它随机抛出低于异常的异常,而Java客户端正在获得Peer not authenticated
异常。如果我重新启动Server Socket application
,则看不到以下异常,并且Java客户端可以成功执行SSL握手
com.ssltunnel.server.MainServerHandshakeThread | IO Error waiting for handshake
javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path validation failed: java.security.cert.CertPathValidatorException: Path does not chain with any of the trust anchors
at sun.security.ssl.Alerts.getSSLException(Unknown Source)
at sun.security.ssl.SSLSocketImpl.fatal(Unknown Source)
at sun.security.ssl.Handshaker.fatalSE(Unknown Source)
at sun.security.ssl.Handshaker.fatalSE(Unknown Source)
at sun.security.ssl.ServerHandshaker.clientCertificate(Unknown Source)
at sun.security.ssl.ServerHandshaker.processMessage(Unknown Source)
at sun.security.ssl.Handshaker.processLoop(Unknown Source)
at sun.security.ssl.Handshaker.process_record(Unknown Source)
at sun.security.ssl.SSLSocketImpl.readRecord(Unknown Source)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(Unknown Source)
at sun.security.ssl.SSLSocketImpl.startHandshake(Unknown Source)
at sun.security.ssl.SSLSocketImpl.startHandshake(Unknown Source)
at com.ssltunnel.server.MainServerHandshakeThread.handshake(MainServerHandshakeThread.java:41)
at com.ssltunnel.server.MainServerHandshakeThread.run(MainServerHandshakeThread.java:71)
at com.ssltunnel.utilities.threading.ShutdownThreadPoolExecutor$1.run(ShutdownThreadPoolExecutor.java:37)
at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
at java.util.concurrent.FutureTask.run(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Caused by: sun.security.validator.ValidatorException: PKIX path validation failed: java.security.cert.CertPathValidatorException: Path does not chain with any of the trust anchors
at sun.security.validator.PKIXValidator.doValidate(Unknown Source)
at sun.security.validator.PKIXValidator.engineValidate(Unknown Source)
at sun.security.validator.Validator.validate(Unknown Source)
at sun.security.ssl.X509TrustManagerImpl.validate(Unknown Source)
at sun.security.ssl.X509TrustManagerImpl.checkTrusted(Unknown Source)
at sun.security.ssl.X509TrustManagerImpl.checkClientTrusted(Unknown Source)
... 16 more
Caused by: java.security.cert.CertPathValidatorException: Path does not chain with any of the trust anchors
at sun.security.provider.certpath.PKIXCertPathValidator.validate(Unknown Source)
at sun.security.provider.certpath.PKIXCertPathValidator.engineValidate(Unknown Source)
at java.security.cert.CertPathValidator.validate(Unknown Source)
... 22 more
下面是我的MainServerHandshakeThread
public class MainServerHandshakeThread implements Runnable {
private final Socket clientSocket;
private final MainServer server;
private static final org.slf4j.Logger LOG = LoggerFactory.getLogger(MainServerHandshakeThread.class.getName());
private boolean done;
private static final long TIMEOUT= 10000000000L;
public static final int NSTOMS = 1000000;
public MainServerHandshakeThread(Socket clientSocket, MainServer server) {
this.clientSocket = clientSocket;
this.server = server;
}
private void handshake() throws IOException, InterruptedException, ClientNotFoundException {
long start = System.nanoTime();
// Changed to want to allow for diagnosing bad certificates
((SSLSocket) clientSocket).setNeedClientAuth(true);
MainServerHandshakeHandler handshake = new MainServerHandshakeHandler();
((SSLSocket) clientSocket).addHandshakeCompletedListener(handshake);
((SSLSocket) clientSocket).startHandshake(); //Line# 41
while (!handshake.isDone() && !done) {
Thread.sleep(10);
long duration = System.nanoTime() - start;
if (duration>TIMEOUT) {
done = true;
LOG.warn("Handshake timeout");
}
}
long stop = System.nanoTime();
LOG.debug("Handshake done in ms: " + ((stop - start) / NSTOMS) );
String serialNumber = handshake.getSerialNumber();
LOG.debug(serialNumber);
}
@Override
public void run() {
try {
handshake();
} catch (IOException ex) {
LOG.error("IO Error waiting for handshake", ex);
} catch (InterruptedException ex) {
LOG.error("Interrupted waiting for handshake", ex);
} catch (ClientNotFoundException ex) {
LOG.warn("Client not found",ex);
} finally {
LOG.debug("Handshake thread is done");
done = true;
}
}
@Override
public void shutdown() {
if (clientSocket!=null) {
SocketUtils.closeQuietly(clientSocket);
}
}
}
我们确实在服务器套接字应用程序中配置了信任库和密钥库,如下所示:
System.setProperty("javax.net.ssl.keyStore", "C:/server/conf/keystore.jks");
System.setProperty("javax.net.ssl.keyStorePassword", KEYSTOREPASS);
System.setProperty("javax.net.ssl.trustStore", "C:/server/conf/keystore.jks");
System.setProperty("javax.net.ssl.trustStorePassword", KEYSTOREPASS);
由于问题已通过重新启动解决,因此只要生产中发生此问题,我们都会重新启动。我们要避免这种情况并解决此问题,请有人帮我解决此随机问题吗?