使用Java Apache FTPClient进行FTP TLS时,获取;握手期间远程主机关闭连接”;

使用Java Apache FTPClient进行FTP TLS时,获取;握手期间远程主机关闭连接”;,java,apache,ftp,ftps,apache-commons-net,Java,Apache,Ftp,Ftps,Apache Commons Net,我在Windows1064X上运行了一个Java(1.8)程序,用于FTP TLS(org.apache.commons.net.FTP): 对于第一个FTP服务器(Microsoft FTP服务),工作正常!调试: 运行: 220 Microsoft FTP服务 认证TLS 234验证命令正常。期待TLS谈判。 使用者******* 演示需要331密码。 通过******* 230用户已登录。 PBSZ 0 200 PBSZ命令成功。 保护蛋白 200保护命令成功。 第一类 200类型设置为I

我在Windows1064X上运行了一个Java(1.8)程序,用于FTP TLS(org.apache.commons.net.FTP):

对于第一个FTP服务器(Microsoft FTP服务),工作正常!调试:

运行:
220 Microsoft FTP服务
认证TLS
234验证命令正常。期待TLS谈判。
使用者*******
演示需要331密码。
通过*******
230用户已登录。
PBSZ 0
200 PBSZ命令成功。
保护蛋白
200保护命令成功。
第一类
200类型设置为I。
SSL:true
系统
215窗口
远程系统是Windows\u NT
协议[Ljava.lang.String;@3f2a3a5
作者:错
壮举
211支持的扩展功能:
朗恩*
UTF8
认证TLS;TLS-C;SSL;TLS-P;
PBSZ
蛋白C;P;
CCC
主办
大小
MDTM
静止流
211端
EPSV
229进入扩展被动模式(| | | 1025 |)
RETR/readme.txt
125数据连接已打开;传输开始。
226传输完成。
退出
再见。
生成成功(总时间:7秒)
对于第二个FTP服务器(FileZilla服务器0.9.59 beta版)出错,请调试:

运行:
220 FileZilla服务器0.9.59测试版
220蒂姆·科塞(Tim。kosse@filezilla-(project.org)
请访问https://filezilla-project.org/
认证TLS
234使用身份验证类型TLS
使用者*******
331 xxx需要密码
通过*******
230已登录
PBSZ 0
200 PBSZ=0
保护蛋白
200保护级别设置为P
第一类
200类型设置为I
SSL:true
系统
FileZilla模拟的215 UNIX
远程系统由FileZilla模拟UNIX
协议[Ljava.lang.String;@246ae04d
作者:错
壮举
211特点:
MDTM
静止流
大小
MLST类型*;尺寸*;修改*;
MLSD
身份验证SSL
认证TLS
保护
PBSZ
UTF8
CLNT
MFMT
EPSV
EPRT
211端
EPSV
229进入扩展被动模式(| | | | 14393 |)
RETR/readme.txt
150打开从“/readme.txt”服务器下载文件的数据通道
错误:握手期间远程主机关闭连接
javax.net.ssl.SSLHandshakeException:握手期间远程主机关闭连接
退出
位于sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1002)
450数据连接的TLS会话未恢复或会话与控制连接不匹配
位于sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1385)
位于sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1413)
位于sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1397)
在org.apache.commons.net.ftp.FTPSClient.\u openDataConnection\u(FTPSClient.java:646)
位于org.apache.commons.net.ftp.FTPClient.\u retrieveFile(FTPClient.java:1899)
位于org.apache.commons.net.ftp.FTPClient.retrieveFile(FTPClient.java:1885)
位于ftps.App_FTP.main(App_FTP.java:96)
原因:java.io.EOFException:SSL对等机错误关闭
位于sun.security.ssl.InputRecord.read(InputRecord.java:505)
位于sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:983)
…还有7个
生成成功(总时间:5秒)
使用FileZilla客户端可以很好地工作(下载/上传文件),但是使用Java代码,我什么都做不了,只需要连接和登录。有什么建议吗?或者其他自动FTP TLS的解决方案吗


重要信息不是异常消息本身,而是日志中的此消息:

450数据连接的TLS会话未恢复或会话与控制连接不匹配

某些FTP服务器确实要求您重新使用TLS会话进行数据连接

ApacheCommonsNetLibrary本机还不支持这一点,但实现它并不困难

如何做到这一点,请参见我对的回答:

我使用Cyberduck库解决了这个问题。
首先,为什么会出现这种握手问题, 因为一些先进的FTP服务器只允许一个会话进行连接和数据传输

1) 控制会话->用于连接
2) 数据会话->数据存储/下载/等

那么如何解决这个问题呢

步骤1-:

首先,您需要从GitHub签出cyberduck回购协议。 从这里开始-:

步骤2-:您将在签出回购中看到FTP和核心模块

步骤3-:将此模块转换为maven并为其创建jar

步骤4-:将这个jar添加到您的项目中,但是这个jar还需要其他依赖项,所以也相应地将它们添加到项目构建路径中

步骤5-:代码片段

public class TestFTPS {
    public static void main(String[] args) throws SocketException, IOException {
        TrustManager[] trustManagers = new TrustManager[] { new X509TrustManager() {
            @Override
            public X509Certificate[] getAcceptedIssuers() {
                // TODO Auto-generated method stub
                return null;
            }
            @Override
            public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                // TODO Auto-generated method stub
            }

            @Override
            public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                // TODO Auto-generated method stub
            }
        } };
        SSLContext sslContext = null;
        try {
            sslContext = SSLContext.getInstance("SSL");
            sslContext.init(null, trustManagers, new SecureRandom());
        } catch (Exception e) {
            e.printStackTrace();
        }
        SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
        Protocol protocol = new FTPTLSProtocol();
        FTPClient client = new FTPClient(protocol, sslSocketFactory, sslContext);
        client.addProtocolCommandListener(new PrintCommandListener(new PrintWriter(System.out)));
        client.connect(ftphostname, port);
        client.execAUTH("TLS"); //SSL
        System.out.println(client.getReplyCode());
        if (client.login(username, password)) {
            client.execPBSZ(0);
            client.execPROT("P");
            String date = "Testing Data Send to provide FTP location";
            client.setFileType(FTP.BINARY_FILE_TYPE);
            client.enterLocalPassiveMode();
            InputStream is = new ByteArrayInputStream(date.getBytes());
            client.storeFile("test.txt", is);
            System.out.print(client.getReplyCode());
        }
    }
}
步骤6-:运行此代码后,您的文件将成功传输到ftp位置

注意-:请在项目中添加所需的jar


希望这能对您有所帮助。

您能解释一下如何执行步骤3吗?
public class TestFTPS {
    public static void main(String[] args) throws SocketException, IOException {
        TrustManager[] trustManagers = new TrustManager[] { new X509TrustManager() {
            @Override
            public X509Certificate[] getAcceptedIssuers() {
                // TODO Auto-generated method stub
                return null;
            }
            @Override
            public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                // TODO Auto-generated method stub
            }

            @Override
            public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                // TODO Auto-generated method stub
            }
        } };
        SSLContext sslContext = null;
        try {
            sslContext = SSLContext.getInstance("SSL");
            sslContext.init(null, trustManagers, new SecureRandom());
        } catch (Exception e) {
            e.printStackTrace();
        }
        SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
        Protocol protocol = new FTPTLSProtocol();
        FTPClient client = new FTPClient(protocol, sslSocketFactory, sslContext);
        client.addProtocolCommandListener(new PrintCommandListener(new PrintWriter(System.out)));
        client.connect(ftphostname, port);
        client.execAUTH("TLS"); //SSL
        System.out.println(client.getReplyCode());
        if (client.login(username, password)) {
            client.execPBSZ(0);
            client.execPROT("P");
            String date = "Testing Data Send to provide FTP location";
            client.setFileType(FTP.BINARY_FILE_TYPE);
            client.enterLocalPassiveMode();
            InputStream is = new ByteArrayInputStream(date.getBytes());
            client.storeFile("test.txt", is);
            System.out.print(client.getReplyCode());
        }
    }
}