[英]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的現有實現。
您可以嘗試以下代碼步驟來使其正常工作:
在項目中添加以下修補的類。 (此類擴展了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); } } } }
使用此修改后的代碼段。
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.