首页 > 解决方案 > Java 1.8.40 路径不与任何信任锚链接

问题描述

Server Socket application在 Java 1.8.40 上作为 Windows 服务运行了独立的 Java,我们有一个 Spring Web 应用程序作为客户端,它使用selfsigned SHA1 RSA 2048证书执行 SSL 握手,Server Socket application然后执行其他操作。我们在keystore.jks中确实有相同的selfsigned SHA1 RSA 2048证书。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);

由于问题正在通过重新启动解决,因此只要在生产中发生此问题,我们就会重新启动。我们想避免这种情况并解决这个问题,有人可以帮我解决这个随机问题吗?

标签: javasocketssslserversocketsslhandshakeexception

解决方案


推荐阅读