首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何建立到FileZilla服务器1.2.0的FTPS数据连接

如何建立到FileZilla服务器1.2.0的FTPS数据连接
EN

Stack Overflow用户
提问于 2022-01-29 09:25:21
回答 1查看 947关注 0票数 2

使用的Java FTPSClient和会话恢复是一个已知的问题。会话恢复是FTPS服务器为数据连接所需的一项安全功能。Apache不支持会话恢复,而FTPSClient API使构建自定义实现变得困难。有几个使用反射的解决方法,例如这个答案和这个公用网络错误条目

我在JDK 11中使用了这样的解决方案(参见下面的片段),并在本地FileZilla服务器上测试了它。它适用于FileZilla服务器0.9.6,但不适用于FileZilla服务器1.2.0,后者是编写本报告时的最新版本。使用该版本时,当试图建立数据连接时,服务器响应如下:

代码语言:javascript
运行
复制
425 Unable to build data connection: TLS session of data connection not resumed.

如前所述,FileZilla Server 0.9.6与我如何进行会话恢复有关,并确保激活了要求会话恢复的设置。

在FileZilla服务器1.2.0中,这些设置现在是隐式设置的,不能通过GUI进行更改,甚至根本不能更改。是否有一些服务器设置可以进行调整以使其工作?或者是我如何实现这个解决方案的问题?有没有人遇到过类似的问题?

这是我正在使用的解决方法:

代码语言:javascript
运行
复制
public class FTPSClientWithSessionResumption extends FTPSClient {

    static {
        System.setProperty("jdk.tls.useExtendedMasterSecret", "false");
        System.setProperty("jdk.tls.client.enableSessionTicketExtension", "false");
    }

    @Override
    protected void _connectAction_() throws IOException {
        super._connectAction_();
        execPBSZ(0);
        execPROT("P");
    }

    @Override
    protected void _prepareDataSocket_(Socket socket) throws IOException {
        if (useSessionResumption && socket instanceof SSLSocket) {
            // Control socket is SSL
            final SSLSession session = ((SSLSocket)_socket_).getSession();
            if (session.isValid()) {
                final SSLSessionContext context = session.getSessionContext();
                try {
                    final Field sessionHostPortCache = context.getClass().getDeclaredField("sessionHostPortCache");
                    sessionHostPortCache.setAccessible(true);
                    final Object cache = sessionHostPortCache.get(context);
                    final Method putMethod = cache.getClass().getDeclaredMethod("put", Object.class, Object.class);
                    putMethod.setAccessible(true);
                    Method getHostMethod;
                    try {
                        getHostMethod = socket.getClass().getMethod("getPeerHost");
                    }
                    catch (NoSuchMethodException e) {
                        // Running in IKVM
                        getHostMethod = socket.getClass().getDeclaredMethod("getHost");
                    }
                    getHostMethod.setAccessible(true);
                    Object peerHost = getHostMethod.invoke(socket);
                    InetAddress iAddr = socket.getInetAddress();
                    int port = socket.getPort();
                    putMethod.invoke(cache, String.format("%s:%s", peerHost, port).toLowerCase(Locale.ROOT), session);
                    putMethod.invoke(cache, String.format("%s:%s", iAddr.getHostName(), port).toLowerCase(Locale.ROOT), session);
                    putMethod.invoke(cache, String.format("%s:%s", iAddr.getHostAddress(), port).toLowerCase(Locale.ROOT), session);
                }
                catch (Exception e) {
                    throw new IOException(e);
                }
            }
            else {
                throw new IOException("Invalid SSL Session");
            }
        }
    }
}

套接字缓存的地址是使用getPeerHostgetInetAddress().getHostName()getInetAddress().getHostAddress()确定的。我尝试了几个组合,做或不做这三个,但我总是得到相同的结果。

编辑

下面是整个会话的服务器日志的屏幕截图:

EN

回答 1

Stack Overflow用户

发布于 2022-03-31 14:09:22

正如这篇StackOverflow文章中所述,可以告诉JVM只使用TLS1.2。

下面是对我有用的最初答案的链接:命令java只使用TLS1.2

您必须在JVM开始时添加一个命令行参数(本例中为:java -Djdk.tls.client.protocols=TLSv1.2 -jar ... <rest of command line here> )。

这个简单的参数适用于我,现在我可以从运行FileZilla的FTP-服务器1.3.0中连接和传输数据

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70903926

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档