首页 > 解决方案 > Java SSL - 重试 SSLSocketException

问题描述

建立安装证书的重试机制。重试直到SSLSocketException不被抛出。我的一项 Springboot 服务间歇性地抛出握手异常,但在几次重新启动后最终可以正常工作,因此也不能说它是证书问题。这是我目前所拥有的。

char[] keyStoreKey = "changeit".toCharArray();
            File file = getJssCaCertFile();
            LOGGER.info("Loading KeyStore {} ...", file);
            KeyStore keyStore;
            try (InputStream in = new FileInputStream(file)) {
                keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
                keyStore.load(in, keyStoreKey);
            }

            SSLContext context = SSLContext.getInstance(sslProtocol == null || sslProtocol.trim().isEmpty() ? SSL_PROTOCOL : sslProtocol);
            TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
            tmf.init(keyStore);
            X509TrustManager defaultTrustManager = (X509TrustManager) tmf.getTrustManagers()[0];
            SavingTrustManager tm = new SavingTrustManager(defaultTrustManager);

            context.init(null, new TrustManager[] { tm }, null);
            SSLSocketFactory factory = context.getSocketFactory();
            LOGGER.info("Opening connection to {}:{} ...", host, port);
            boolean installCerts = false;
            try (SSLSocket socket = (SSLSocket) factory.createSocket(host, port)) {
                socket.setSoTimeout(SSL_TIMEOUT);
                try {
                    LOGGER.info("Starting SSL handshake...");
                    socket.startHandshake();
                    installCerts = true;
                    LOGGER.info("No errors, certificate is already trusted");
                } catch (SSLException e) {
                    LOGGER.info("Certificate is not trusted - try getting it and installing it");
                    if(retryCount < 10) {
                        return null;
                    }
                }
            }

chain尝试 10 次后,使用onTrustManager和 add to检查证书keystore

            if(installCerts || retryCount == 10) {
                X509Certificate[] chain = tm.chain;
                if (chain == null || chain.length == 0) {
                    throw new CryptoUtilException("Error in getting server certificate. Host: " + host + ". Port: " + port);
                }

                LOGGER.info("Server sent {} certificate(s):", chain.length);
                AtomicInteger counter = new AtomicInteger(0);
                Stream.of(chain).forEach(certificate -> {
                    String alias = host + "-" + counter.getAndIncrement();
                    try {
                        keyStore.setCertificateEntry(alias, certificate);
                        LOGGER.info("Certificate {} added successfully", alias);
                    } catch (KeyStoreException e) {
                        LOGGER.error("Error while adding {} into keystore", alias);
                    }
                });

                OutputStream out = new FileOutputStream(JSSECACERTS);
                keyStore.store(out, keyStoreKey);
                out.close();
            }

有没有更好的方法来处理这个问题,而不是循环直到没有抛出异常。

感谢您的建议!

标签: javaspring-bootspring-securityssl-certificate

解决方案


推荐阅读