使用Apache Commons API连接到Linux FTPS Server时,没有Trusted Cert错误

时间:2019-03-23 06:04:44

标签: keystore truststore

我正在尝试连接到几个Linux FTPS服务器(一个是Red Hat 5.11,另一个是Red Hat 6.8),并使用org.apache.commons将文件从Linux FTPS服务器下载到我的本地Windows Server。 .net.ftp.FTPSClient。

我正尝试以两种不同的方式使用Apache Commons API进行连接。

1。使用第一种方法,我可以连接到两个Linux主机,然后将测试文件testftps.txt从两个远程Linux服务器成功下载到我的本地Windows服务器。我的第一个连接方法是connectToFtp(),如下面的代码所示。它使用位于我的Eclipse Java项目构建路径中定义的路径中的certificate.jks。该文件具有一个加密密码,用于保护JKS中的私钥,并且帐户ID也与JKS相关联。

我在Linux主机hostname1和hostname2上都创建了/tmp/testftps.txt文件。我只是将host变量更改为指向hostname1或hostname2,它使用下面显示的downloadFiles()函数代码将文件testftps.txt成功地从相应的主机下载到了本地Windows服务器。

代码:

private void connectToFtp() throws Exception {
    try {
        ftpClient = new FTPSClient("SSL");
        String host = "hostname1";
        String user = "accountid";
        String password = "";
        String jksFileName = "certificate.jks";
        String jksFilePassword = "encryptionpassword";

        File jksFile = new File(ClassLoader.getSystemResource(jksFileName).toURI());
        String jksFilename = jksFile.getName();
        ftpClient.setKeyManager(KeyManagerUtils.createClientKeyManager(jksFile, jksFilePassword));
        ftpClient.connect(host, 2121);
        ftpClient.enterLocalPassiveMode();
        ftpClient.login(user, password);
        ftpClient.execPBSZ(0);
        ftpClient.execPROT("P");
        ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
    } catch(Exception e) {
        System.out.println("Failed to connect: Exception=" + e);
        throw e;
    }
}

public void downloadFiles() throws Exception {
    try {
        String specifiedRemoteFileName = "testftps.txt";
        File localFile = new File(localFilePath + "/" + specifiedRemoteFileName);
        OutputStream outputStream = new BufferedOutputStream(new FileOutputStream(localFile));
        String remoteFile = remoteFilePath + "/" + specifiedRemoteFileName;
        boolean downloaded = ftpClient.retrieveFile(remoteFile, outputStream);
        if (downloaded) {
            System.out.println("File has been downloaded successfully to local destination " + localFile.getAbsolutePath());
        } else {
            System.out.println("File " + remoteFile + " was not downloaded from remote server.");
        }
        outputStream.close();
    }
    catch(Exception e) {
        System.out.println("Error during download...");
        throw e;
    }
}

2。对于第二个程序,我使用相同的certificate.jks,accountid和加密密码,相同的Apache Commons API,并且试图将相同的testftps.txt从hostname1和hostname2提取到本地Windows VM。对于第二种方法,我的连接机制connectToFtpUsing_TrustStoreKeystore()稍有不同,如下所示。尽管它使用相同的certificate.jks,但它获取Truststore,Keystore,使用keyManagetFactory,TrustManagerFactory SSLContext等。我仍在使用org.apache.commons.net.ftp.FTPSClient对象,但是使用此方法,连接对于远程Linux FTPS服务器主机名1,我可以下载很好,但是对于远程Linux FTPS服务器主机名2和其他一些主机,程序给出了Exception in thread "main" javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: No trusted certificate found,如下所示。

如果您能查看下面的连接方法并将其与以前的方法进行比较,我将不胜感激,请让我知道为什么上面的方法connectToFtp()可以从所有Linux FTPS Server成功下载文件,而下面的{{1 }}仅成功连接到少数FTPS服务器,并且即使两个程序使用相同的CERTIFICATE.JKS文件和相同的Apache Commons FTPSClient API,也无法通过connectToFtpUsing_TrustStoreKeystore()连接到许多服务器。如何解决?

No trusted certificate found ERROR

使用第二种方法得到的错误的堆栈跟踪:

    try {
        ftpClient = new FTPSClient("TLS", Boolean.FALSE);
        KeyStore keyStore = getKeyStore();
        KeyStore trustStore = getTrustStore(keyStore);
        keyManagerFactory = KeyManagerFactory.getInstance("SunX509");
        trustManagerFactory = TrustManagerFactory.getInstance("SunX509");
        keyManagerFactory.init(keyStore, "encryptionpassword".toCharArray());
        trustManagerFactory.init(trustStore);
        SSLContext sslContext = SSLContext.getInstance("TLS");
        sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null);
        FTPSSocketFactory socketFactory = getSocketFactory(sslContext);
        ftpClient.setRemoteVerificationEnabled(false);
        ftpClient.setSocketFactory(socketFactory);
        ftpClient.setNeedClientAuth(false);
        ftpClient.setBufferSize(0);
        ftpClient.setControlEncoding("UTF-8");
        ftpClient.setKeyManager(keyManagerFactory.getKeyManagers()[0]);
        ftpClient.setTrustManager(trustManagerFactory.getTrustManagers()[0]);
        ftpClient.connect("hostname", Integer.parseInt("2121"));
        ftpClient.execPBSZ(0);
        ftpClient.execPROT("P");
        ftpClient.login("accountid", "encryptionpassword");
        ftpClient.enterLocalPassiveMode();
        ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
    } catch(Exception e) {
        System.out.println("Failed to connect using Trustore keystore" + e);
        throw e;
    }
}

private static KeyStore getKeyStore() throws Exception {
    KeyStore keyStore = KeyStore.getInstance("JKS");
    InputStream inputStream = new FileInputStream(new File("C:\\blah\\blah\\certificate.jks"));
    keyStore.load(inputStream, "encryptionpassword".toCharArray());
    return keyStore;
}

private static KeyStore getTrustStore(KeyStore keyStore) throws Exception {
    KeyStore trustStore = KeyStore.getInstance("JKS");
    trustStore.load(null);
    for (Enumeration < String > t = keyStore.aliases(); t.hasMoreElements();) {
        String alias = t.nextElement();
        if (keyStore.isKeyEntry(alias)) {
            Certificate[] keyStore_certificate = keyStore.getCertificateChain(alias);
            X509Certificate x5091 = (X509Certificate) keyStore_certificate[1];
            trustStore.setCertificateEntry(x5091.getSubjectDN().toString(), x5091);
        }
    }
    return trustStore;
}

private static FTPSSocketFactory getSocketFactory(SSLContext sslContext) throws Exception {
    FTPSSocketFactory socketFactory = new FTPSSocketFactory(sslContext) {@Override
        public Socket createSocket() throws IOException {
            return new Socket();
        }
    };
    return socketFactory;
}

0 个答案:

没有答案