[英]How to connect to FTPS server with reuse sessions?
我在我的 android 應用程序中使用 Apache Commons FTP 庫。
我正在嘗試從我的應用程序(使用 Android Studio)連接到我的 FTPS 服務器,然后上傳一些文件。
然而,當我想overiding方法重用會話_prepareDataSocket_
從FTPSClient
,我總有大約同樣的錯誤: java.lang.NoSuchFieldException: sessionHostPortCache
。 我已嘗試使用其他帖子中的代碼: 如何使用相同的 TLS 會話通過數據連接連接到 FTPS 服務器? 或使用 FTPS 將文件從 android 傳輸到服務器你知道我為什么會出現這個錯誤嗎?
我正在使用帶有 jdk 1.8 的 Android Studio。
我感謝任何幫助,謝謝。
String server = "ftp.[HIDDEN]";
int port = 21;
String user = "[HIDDEN]";
String pass = "[HIDDEN]";
System.setProperty("jdk.tls.useExtendedMasterSecret", "false");
SSLSessionReuseFTPSClient ftpClient = new SSLSessionReuseFTPSClient("SSL");
ftpClient.addProtocolCommandListener(new PrintCommandListener(new PrintWriter(System.out), true));
ftpClient.connect(server, port);
System.out.println("Connected to " + server + " on " + port);
ftpClient.login(user, pass);
ftpClient.execPBSZ(0);
ftpClient.execPROT("P");
ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
ftpClient.enterLocalPassiveMode();
// transfer files
InputStream input;
input = new FileInputStream(local);
ftpClient.storeFile(remote, input);
input.close();
ftpClient.noop(); // check that control connection is working OK
ftpClient.logout();
public class SSLSessionReuseFTPSClient extends FTPSClient {
public SSLSessionReuseFTPSClient(String protocol) {
super(protocol);
}
// adapted from: https://trac.cyberduck.io/changeset/10760
@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");
}
}
}
}
220---------- Welcome to Pure-FTPd [privsep] [TLS] ----------
07-22 09:53:59.516 9529-9561/com.example.test I/System.out: 220-You are user number 1 of 50 allowed.
07-22 09:53:59.516 9529-9561/com.example.test I/System.out: 220-Local time is now 11:54. Server port: 21.
07-22 09:53:59.516 9529-9561/com.example.test I/System.out: 220-This is a private system - No anonymous login
07-22 09:53:59.516 9529-9561/com.example.test I/System.out: 220-IPv6 connections are also welcome on this server.
07-22 09:53:59.516 9529-9561/com.example.test I/System.out: 220 You will be disconnected after 15 minutes of inactivity.
07-22 09:53:59.519 9529-9561/com.example.test I/System.out: AUTH TLS
07-22 09:53:59.533 9529-9561/com.example.test I/System.out: 234 AUTH TLS OK.
07-22 09:53:59.561 9529-9550/com.example.test D/EGL_emulation: eglMakeCurrent: 0xadc34d60: ver 2 0 (tinfo 0xadc394d0)
07-22 09:53:59.589 9529-9550/com.example.test D/EGL_emulation: eglMakeCurrent: 0xadc34d60: ver 2 0 (tinfo 0xadc394d0)
07-22 09:53:59.593 9529-9561/com.example.test I/System.out: Connected to ftp.[HIDDEN] on 21
07-22 09:53:59.597 9529-9561/com.example.test I/System.out: USER *******
07-22 09:53:59.609 9529-9561/com.example.test I/System.out: 331 User [HIDDEN] OK. Password required
07-22 09:53:59.610 9529-9561/com.example.test I/System.out: PASS *******
07-22 09:53:59.613 9529-9550/com.example.test D/EGL_emulation: eglMakeCurrent: 0xadc34d60: ver 2 0 (tinfo 0xadc394d0)
07-22 09:53:59.695 9529-9550/com.example.test D/EGL_emulation: eglMakeCurrent: 0xadc34d60: ver 2 0 (tinfo 0xadc394d0)
07-22 09:53:59.701 9529-9561/com.example.test I/System.out: 230 OK. Current restricted directory is /
07-22 09:53:59.702 9529-9561/com.example.test I/System.out: PBSZ 0
07-22 09:53:59.714 9529-9561/com.example.test I/System.out: 200 PBSZ=0
07-22 09:53:59.717 9529-9561/com.example.test I/System.out: PROT P
07-22 09:53:59.727 9529-9561/com.example.test I/System.out: 200 Data protection level set to "private"
07-22 09:53:59.729 9529-9561/com.example.test I/System.out: TYPE I
07-22 09:53:59.743 9529-9561/com.example.test I/System.out: 200 TYPE is now 8-bit binary
07-22 09:53:59.743 9529-9561/com.example.test I/System.out: PASV
07-22 09:53:59.757 9529-9550/com.example.test D/EGL_emulation: eglMakeCurrent: 0xadc34d60: ver 2 0 (tinfo 0xadc394d0)
07-22 09:53:59.758 9529-9561/com.example.test I/System.out: 227 Entering Passive Mode (5,134,13,241,188,161)
07-22 09:53:59.777 9529-9550/com.example.test D/EGL_emulation: eglMakeCurrent: 0xadc34d60: ver 2 0 (tinfo 0xadc394d0)
07-22 09:53:59.782 9529-9561/com.example.test I/System.out: STOR pictures/test 18.07 1431/test 18.07 1431_19.6.2019_0.32.15.667.jpg
07-22 09:53:59.792 9529-9561/com.example.test I/System.out: 150 Accepted data connection
07-22 09:53:59.793 9529-9561/com.example.test W/System.err: java.io.IOException: java.lang.NoSuchFieldException: sessionHostPortCache
07-22 09:53:59.793 9529-9561/com.example.test W/System.err: at com.example.test.functions.SSLSessionReuseFTPSClient._prepareDataSocket_(SSLSessionReuseFTPSClient.java:54)
07-22 09:53:59.793 9529-9561/com.example.test W/System.err: at org.apache.commons.net.ftp.FTPSClient._openDataConnection_(FTPSClient.java:628)
07-22 09:53:59.793 9529-9561/com.example.test W/System.err: at org.apache.commons.net.ftp.FTPClient._storeFile(FTPClient.java:653)
07-22 09:53:59.793 9529-9561/com.example.test W/System.err: at org.apache.commons.net.ftp.FTPClient.__storeFile(FTPClient.java:639)
07-22 09:53:59.793 9529-9561/com.example.test W/System.err: at org.apache.commons.net.ftp.FTPClient.storeFile(FTPClient.java:2030)
07-22 09:53:59.793 9529-9561/com.example.test W/System.err: at com.example.test.functions.FTPfunctions2$BackGroundWorker.doInBackground(FTPfunctions2.java:81)
07-22 09:53:59.793 9529-9561/com.example.test W/System.err: at com.example.test.functions.FTPfunctions2$BackGroundWorker.doInBackground(FTPfunctions2.java:41)
07-22 09:53:59.794 9529-9561/com.example.test W/System.err: at android.os.AsyncTask$2.call(AsyncTask.java:292)
07-22 09:53:59.794 9529-9561/com.example.test W/System.err: at java.util.concurrent.FutureTask.run(FutureTask.java:237)
07-22 09:53:59.794 9529-9561/com.example.test W/System.err: at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
07-22 09:53:59.794 9529-9561/com.example.test W/System.err: at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
07-22 09:53:59.794 9529-9561/com.example.test W/System.err: at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
07-22 09:53:59.794 9529-9561/com.example.test W/System.err: at java.lang.Thread.run(Thread.java:818)
07-22 09:53:59.794 9529-9561/com.example.test W/System.err: Caused by: java.lang.NoSuchFieldException: sessionHostPortCache
07-22 09:53:59.794 9529-9561/com.example.test W/System.err: at java.lang.Class.getDeclaredField(Class.java:890)
07-22 09:53:59.794 9529-9561/com.example.test W/System.err: at com.example.test.functions.SSLSessionReuseFTPSClient._prepareDataSocket_(SSLSessionReuseFTPSClient.java:42)
07-22 09:53:59.794 9529-9561/com.example.test W/System.err: ... 12 more
當我將 java.security 更改為使用 SunJSSE 以外的 ssl 安全提供程序時,我遇到了同樣的錯誤。 特別是在我的情況下,我將其更改為:security.provider.4=org.bouncycastle.jsse.provider.BouncyCastleJsseProvider 而不是 security.provider.4=com.sun.net.ssl.internal.ssl.Provider
1) 檢查您的 java.security 文件。
2) 我在類中添加了一條日志消息,該消息顯示了實際使用的 SSLSessionContext 的實現。
logger.debug("sessionContext calss = " + sessionContext.getClass().getCanonicalName());
final Field sessionHostPortCache = sessionContext.getClass().getDeclaredField("sessionHostPortCache");
我確實發現 BouncyCastle org.bouncycastle.jsse.provider.ProvSSLSessionContext 類沒有 sessionHostPortCache 成員。 你可以試試這個來發現問題。
獲得 java.lang.NoSuchFieldException 的另一個原因是 JRE 字節碼經過混淆。 因此 sessionHostPortCache 字段可以命名為例如“b”。
您可以通過在 IDE 中打開 SSLSessionContext.class 來檢查這一點,如果您安裝了反編譯器插件,它將顯示源代碼。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.