環境:我在64位Windows 7上使用Sun Java JDK 1.8.0_60,使用Spring Integration 4.1.6(內部似乎使用Apache Commons Net 3.3進行FTPS訪問)。如何使用相同的TLS會話連接到具有數據連接的FTPS服務器?
我試圖與我們的應用程序集成從我們客戶的FTPS服務器自動下載。我已經成功地使用了Spring Integration的SFTP服務器,沒有任何問題,但沒有任何問題,但這是客戶第一次要求我們使用FTPS,並且讓它連接非常令人費解。雖然在我的真實應用程序中,我使用XML beans配置Spring Integration,試圖瞭解什麼不起作用我正在使用以下測試代碼(儘管我在此匿名實際的主機/用戶名/密碼):
final DefaultFtpsSessionFactory sessionFactory = new DefaultFtpsSessionFactory();
sessionFactory.setHost("XXXXXXXXX");
sessionFactory.setPort(990);
sessionFactory.setUsername("XXXXXXX");
sessionFactory.setPassword("XXXXXXX");
sessionFactory.setClientMode(2);
sessionFactory.setFileType(2);
sessionFactory.setUseClientMode(true);
sessionFactory.setImplicit(true);
sessionFactory.setTrustManager(TrustManagerUtils.getAcceptAllTrustManager());
sessionFactory.setProt("P");
sessionFactory.setProtocol("TLSv1.2");
sessionFactory.setProtocols(new String[]{"TLSv1.2"});
sessionFactory.setSessionCreation(true);
sessionFactory.setCipherSuites(new String[]{"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"});
final FtpSession session = sessionFactory.getSession();
//try {
final FTPFile[] ftpFiles = session.list("/");
logger.debug("FtpFiles: {}", (Object[]) ftpFiles);
//} catch (Exception ignored) {}
session.close();
我使用-Djavax.net.debug=all
運行此代碼以獲取打印的所有TLS調試信息。
到FTPS服務器的主要「控制」連接工作正常,但當它試圖打開列表(或任何其他數據連接我試過)的數據連接時,我得到javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
,由java.io.EOFException: SSL peer shut down incorrectly
造成。如果我去掉吞嚥的例外趕上圍繞session.list
命令塊,然後我可以看到(雖然javax.net.debug輸出)服務器拒絕數據連接SSL握手後發送的以下消息:
main, READ: TLSv1.2 Application Data, length = 129
Padded plaintext after DECRYPTION: len = 105
0000: 34 35 30 20 54 4C 53 20 73 65 73 73 69 6F 6E 20 450 TLS session
0010: 6F 66 20 64 61 74 61 20 63 6F 6E 6E 65 63 74 69 of data connecti
0020: 6F 6E 20 68 61 73 20 6E 6F 74 20 72 65 73 75 6D on has not resum
0030: 65 64 20 6F 72 20 74 68 65 20 73 65 73 73 69 6F ed or the sessio
0040: 6E 20 64 6F 65 73 20 6E 6F 74 20 6D 61 74 63 68 n does not match
0050: 20 74 68 65 20 63 6F 6E 74 72 6F 6C 20 63 6F 6E the control con
0060: 6E 65 63 74 69 6F 6E 0D 0A nection..
看起來發生了什麼(這是我第一次處理FTPS,雖然我之前已經處理過普通的FTP)是服務器通過控制和數據連接確保身份驗證和加密的方式是,在「正常」 TLS連接建立控制連接和身份驗證發生在那裏,每個數據連接都需要客戶端連接相同的TLS會話。這對我來說很有意義,因爲它應該如何工作,但Apache Commons Net FTPS實現似乎沒有這樣做。它似乎試圖建立一個新的TLS會話,因此服務器拒絕嘗試。
根據this question about resuming SSL sessions in JSSE,似乎Java爲每個主機/帖子組合設定或需要不同的會話。我的假設是,由於FTPS數據連接位於與控制連接不同的端口上,因此它不會找到現有會話並嘗試建立新連接,因此連接失敗。
我看到三個主要的可能性:
- 服務器未按照要求數據端口上的相同TLS會話控制端口上FTPS標準。我可以使用FileZilla 3.13.1連接到服務器(使用與我在代碼中使用的主機/用戶/密碼相同的服務器)。服務器在登錄時將自己標識爲「FileZilla Server 0.9.53 beta」,所以這可能是某種專有的FileZilla做事方式,我需要做一些奇怪的事情來說服Java使用相同的TLS會話。
- Apache Commons Net客戶端實際上並不遵循FTPS標準,只允許一些不允許保護數據連接的子集。這看起來很奇怪,因爲它似乎是從Java內部連接到FTPS的標準方式。
- 我完全錯過了一些東西,並且誤診了這件事。
我很感謝你提供關於如何連接到這種FTPS服務器的任何方向。謝謝。
請參閱此鏈接瞭解詳情https://stackoverflow.com/questions/46631315/when-using-java-apache-ftpclient-for-ftp-tls-getting-remote-host-closed -connect/48616779#48616779 –