Android - Повторное использование сеанса FTPS - Нет поля sessionHostPortCache - PullRequest
0 голосов
/ 21 апреля 2020

Я разрабатываю приложение на Android с Android Studio и хочу использовать FTP для отправки файлов на сервер. Мне нужно поддерживать повторное использование сеанса, так как сервер размещен у поставщика услуг хостинга, и у него, очевидно, включено повторное использование сеанса.


Я нашел этот взлом отражения в этом сообщении , используемом многими чтобы сделать это возможным:

// adapted from:
// https://trac.cyberduck.io/browser/trunk/ftp/src/main/java/ch/cyberduck/core/ftp/FTPClient.java
@Override
protected void _prepareDataSocket_(final Socket socket) throws IOException {
    if (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 method = cache.getClass().getDeclaredMethod("put", Object.class, Object.class);
                method.setAccessible(true);
                method.invoke(cache, String
                        .format("%s:%s", socket.getInetAddress().getHostName(), String.valueOf(socket.getPort()))
                        .toLowerCase(Locale.ROOT), session);
                method.invoke(cache, String
                        .format("%s:%s", socket.getInetAddress().getHostAddress(), String.valueOf(socket.getPort()))
                        .toLowerCase(Locale.ROOT), session);
            } catch (NoSuchFieldException e) {
                throw new IOException(e);
            } catch (Exception e) {
                throw new IOException(e);
            }
        } else {
            throw new IOException("Invalid SSL Session");
        }
    }
}

Вот код, который использует SSLSessionReuseFTPSClient:

System.setProperty("jdk.tls.useExtendedMasterSecret", "false");

String host = "xxxxxxxx";
String user = "xxxxxxxx";
String password = "xxxxxxxx";
String directory = "xxxxxxxx";

ProtocolCommandListener listener = new MyProtocolCommandListener(host);

SSLSessionReuseFTPSClient client = new SSLSessionReuseFTPSClient("TLS", false);
client.addProtocolCommandListener(listener);

try {
    client.connect(host);
    client.execPBSZ(0);
    client.execPROT("P");

    if (client.login(user, password)) {
        Log.w("myApp", "Logged in as " + user + " on " + host + ".");
    }

    if (client.changeWorkingDirectory(directory)) {
        Log.w("myApp", "Working directory changed to " + directory + ".");
    }

    client.enterLocalPassiveMode();

    InputStream input = new FileInputStream(file);

    if (client.storeFile(file.getName(), input)) {
        Log.w("myApp", "File " + file.getName() + " sent to " + host + ".");
    } else {
        Log.w("myApp", "Couldn't send file " + file.getName() + " to " + host + ".");
        Log.w("myApp", "Reply: " + client.getReplyString());
    }

    client.logout();
    client.disconnect();
} catch (Exception e) {
    e.printStackTrace();
}

Я впервые попробовал в Eclipse, и это сработало. Затем я попытался реализовать это в своем приложении Android, но я получаю эту ошибку:

java.io.IOException: java.lang.NoSuchFieldException: No field sessionHostPortCache in class Lcom/android/org/conscrypt/ClientSessionContext; (declaration of 'com.android.org.conscrypt.ClientSessionContext' appears in /system/framework/conscrypt.jar)

Я заметил, что когда я выполняю код в Eclipse и печатаю имя класса context , Я получаю это: sun.security.ssl.SSLSessionContextImpl, но в Android Studio я получаю: com.android.org.conscrypt.ClientSessionContext.


Я искал почти два дня подряд, и я просто недостаточно опытен знать, что случилось. Почему com.android.org.conscrypt.ClientSessionContext используется вместо sun.security.ssl.SSLSessionContextImpl? Я проверяю файл java .security и из того, что я вижу, следует использовать sun.security.ssl.SSLSessionContextImpl.

Если бы кто-то мог помочь мне с этим, я был бы безумно благодарен.

Наконец, Вот некоторая информация, которая может быть полезна:

Android Studio 3.6.2
commons-net-3.6
openjdk version "1.8.0_212-release"
OpenJDK Runtime Environment (build 1.8.0_212-release-1586-b04)
OpenJDK 64-Bit Server VM (build 25.212-b04, mixed mode)

Спасибо!

...