簡體   English   中英

使用FTPS將文件從android傳輸到服務器

[英]Transfer files from android with FTPS to the server

我在我的Android應用程序中使用Apache Commons FTP庫

我通過FTPS建立連接,雖然它與服務器完美連接,但在傳輸文件時遇到問題。

出於安全原因,訂購應用程序的客戶端在使用PROT P時請求在數據連接上恢復TLS會話。

因此,我在服務器上啟用了此選項:

在此輸入圖像描述

正如我所說,我可以連接到服務器,但不能傳輸文件。 如果我取消激活“使用PROT P時數據連接上所需的TLS會話恢復”框,則傳輸正常。

我正在尋找一種使用庫進行文件傳輸的方法,但是沒有成功,我知道必須有一種方法。

我給你相關代碼的一部分:

TransferImagenesFTP.ftpClient = new FTPSClient();

TransferImagenesFTP.ftpClient.connect(InetAddress.getByName("XXX_XXX_XX_X"), 26);
TransferImagenesFTP.ftpClient.enterLocalPassiveMode();
TransferImagenesFTP.ftpClient.setBufferSize(1024000);
TransferImagenesFTP.ftpClient.login("xxxxxx", "zzzzzz");
TransferImagenesFTP.ftpClient.execPROT("P");
TransferImagenesFTP.ftpClient.type(FTP.BINARY_FILE_TYPE);

我感謝任何幫助,謝謝。

您可以嘗試以下代碼,我希望它也適用於您的情況。

該代碼使用Apache Commons vsf2通過安全ftp連接(SFTP)上傳文件

try {
  String filepath = "<FILE PATH>";
  String serverAddress = "<FTP SERVER ADDRESS>";
  String userId = "<FTP USER ID>";
  String password = "<FTP PASSWORD>";
  String remoteDirectory = "<FTP DIRECTORY TO UPLOAD TO>";   
  String keyPath = "<PATH TO YOUR KEY>";   
  String passPhrase = "<PASSWORD FOR YOUR KEY>";   


  File file = new File(filepath);
  if (!file.exists())
    throw new RuntimeException("Error. File not found");

  //Initializes the file manager
  StandardFileSystemManager manager = new StandardFileSystemManager();
  manager.init();

  //Setup our SFTP configuration
  FileSystemOptions opts = new FileSystemOptions();
  SftpFileSystemConfigBuilder.getInstance().setStrictHostKeyChecking(opts, "no");
  SftpFileSystemConfigBuilder.getInstance().setUserDirIsRoot(opts, true);
  SftpFileSystemConfigBuilder.getInstance().setTimeout(opts, 10000);

  // Create local file object
  FileObject localFile = manager.resolveFile(file.getAbsolutePath());

  // Create remote file object
  FileObject remoteFile = manager.resolveFile(createConnectionString(serverAddress, userId, password, keyPath, passPhrase, fileToFTP), createDefaultOptions(keyPath, passPhrase));


  // Copy local file to sftp server
  remoteFile.copyFrom(localFile, Selectors.SELECT_SELF);
  System.out.println("File upload successful");

}
catch (Exception ex) {
  ex.printStackTrace();
  return false;
}
finally {
  manager.close();
}

您可以在Apache Commons VFS文檔中查看更多信息

編輯

在理解了FTPS背后的邏輯和@ riyaz-ali的帖子之后,並參考了你對本文的評論中的鏈接

Apache FTP客戶端存在問題,它不支持TLS會話恢復。 您可以修補Apache Commons Library的現有實現。

您可以嘗試以下代碼步驟來使其正常工作:

  1. 在項目中添加以下修補的類。 (此類擴展了Apache commons中給出的補丁中現有的FTPS實現)

     import java.io.IOException; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.net.Socket; import java.util.Locale; import javax.net.ssl.SSLSession; import javax.net.ssl.SSLSessionContext; import javax.net.ssl.SSLSocket; import org.apache.commons.net.ftp.FTPSClient; import com.google.common.base.Throwables; public class PatchedFTPSClient extends FTPSClient { @Override protected void _prepareDataSocket_(final Socket socket) throws IOException { if(socket instanceof SSLSocket) { final SSLSession session = ((SSLSocket) _socket_).getSession(); 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); final String key = String.format("%s:%s", socket.getInetAddress().getHostName(), String.valueOf(socket.getPort())).toLowerCase(Locale.ROOT); method.invoke(cache, key, session); } catch(Exception e) { throw Throwables.propagate(e); } } } } 
  2. 使用此修改后的代碼段。

     TransferImagenesFTP.ftpClient = new PatchedFTPSClient(); TransferImagenesFTP.ftpClient.connect(InetAddress.getByName<SERVER-ADDRESS>"), 26); TransferImagenesFTP.ftpClient.login("<USERNAME>", "<PASSWORD>"); TransferImagenesFTP.ftpClient.execPBSZ(0); TransferImagenesFTP.ftpClient.execPROT("P"); TransferImagenesFTP.ftpClient.enterLocalPassiveMode(); //Now use the FTP client to upload the file as usual. 

    希望這對您有用,並將解決您的問題。

在您的情況下,問題是Apache FTPSClient不支持TLS會話恢復,因此,當您嘗試傳輸文件時失敗。

理解問題

當您通過TLS連接到FTP服務器時,服務器控制連接上啟動與客戶端的安全ssl會話 然后,客戶端通過發送PASV命令進入被動模式 ,作為響應,服務器打開一個隨機的非特權端口,並將端口號發送給客戶端。 此端口表示數據連接 現在要安全地連接到這個新端口,客戶端必須重新使用它已經與控制連接上的服務器的現有TLS會話。

為什么要重用TLS會話?

不需要會話恢復允許會話竊取攻擊。 FTP的問題是數據連接不驗證客戶端。
如果服務器/客戶端不重用現有的TLS會話,則攻擊者可能會連接到數據端口並上傳惡意軟件。 因此,為了防止此類攻擊,FTP服務器要求客戶端重用已經建立的會話。

在您的情況下, Apache FTPSClient無法重用會話(這是一個已知問題 ),因此服務器認為您的客戶端是未經授權的並拒絕傳輸。

查看Wealthfront文章 ,了解如何修補和示例實現。

資料來源:

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM