android ftp file tranfer over explicit TLS

匿名 (未验证) 提交于 2019-12-03 08:28:06

问题:

I'm posting this question after have tried over and over again to get it working, with no success. I trying to implement a FTP file transfer in android, using apache commons library. The communication must be done through explicit TLS authentication. I can successfully login, connect to the server and list files, but whenever i try to get or store a file, I always get a timeout exception, also with very large timeout value, even for a 2Kb txt file. This is my code:

 FTPSClient ftpClient = new FTPSClient("TLS", false);     ftpClient.addProtocolCommandListener(new PrintCommandListener(new PrintWriter(System.out))); KeyManagerFactory kmf = getInstance(KeyManagerFactory.getDefaultAlgorithm()); kmf.init(null, null); KeyManager km = kmf.getKeyManagers()[0]; ftpClient.setKeyManager(km); ftpClient.setBufferSize(1024 * 1024); ftpClient.setConnectTimeout(900000); ftpClient.connect(InetAddress.getByName("server ip address"), 990); // Set protection buffer size ftpClient.execPBSZ(0); // // Set data channel protection to private ftpClient.execPROT("P"); ftpClient.login("user", "password"); ftpClient.changeWorkingDirectory("/"); ftpClient.setSoTimeout(900000); ftpClient.setFileType(FTP.BINARY_FILE_TYPE); ftpClient.enterLocalPassiveMode(); buffIn = new BufferedInputStream(new FileInputStream(file.getAbsolutePath()));  //this works FTPFile[] files = ftpClient.listFiles(); final OutputStream os = new FileOutputStream(finalStoragePath + "/OK.txt"); //this returns immediatly with false result boolean getResult=ftpClient.retrieveFile("OK.txt", os); //this always fail for timeout boolean result = ftpClient.storeFile( picture.getName(), buffIn ); 

I can't find any example of this specific situation, all examples out there, are about normal FTP connection, which I can achieve with no problems. Did any of you had a similar problem? I really need a solution, I have to deliver the project ASAP.

thanks.

回答1:

I have finally found a solution, the solution was to set the trust manager to accept all certificates. here is the code for those who are experiencing similar problems, maby it can be improved and/or optimized, but it works:

FTPSClient ftpClient = new FTPSClient("TLS", false); try {     TrustManager[] trustManager = new TrustManager[] { new X509TrustManager() {         @Override         public X509Certificate[] getAcceptedIssuers() {             return null;         }          @Override         public void checkClientTrusted(X509Certificate[] certs, String authType) {         }          @Override         public void checkServerTrusted(X509Certificate[] certs, String authType) {         }     } };      ftpClient.setTrustManager(trustManager[0]);     KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());     kmf.init(null, null);     KeyManager km = kmf.getKeyManagers()[0];     ftpClient.setKeyManager(km);     ftpClient.setBufferSize(1024 * 1024);     ftpClient.setConnectTimeout(100000);     ftpClient.connect(InetAddress.getByName("ipaddress"), 990);     ftpClient.setSoTimeout(100000);      if (ftpClient.login("user", "password")) {         ftpClient.execPBSZ(0);         ftpClient.execPROT("P");         ftpClient.changeWorkingDirectory("/");         // 250 = directory succesfully changed         if (ftpClient.getReplyString().contains("250")) {             ftpClient.setFileType(FTP.BINARY_FILE_TYPE);             ftpClient.enterLocalPassiveMode();             BufferedInputStream buffIn = null;              for (File picture : pictures) {                 buffIn = new BufferedInputStream(new FileInputStream(picture.getAbsolutePath()));                 boolean result = ftpClient.storeFile(picture.getName(), buffIn);                 try {                     buffIn.close();                 } catch (Exception e) {                 }                 if (result)                     picture.delete();             }         }     }  } catch (SocketException e) {     Log.e("APPTAG", e.getStackTrace().toString()); } catch (UnknownHostException e) {     Log.e("APPTAG", e.getStackTrace().toString()); } catch (IOException e) {     Log.e("APPTAG", e.getStackTrace().toString()); } catch (Exception e) {     Log.e("APPTAG", e.getStackTrace().toString()); } finally {     try {         ftpClient.logout();     } catch (Exception e2) {     }     try {         ftpClient.disconnect();     } catch (Exception e2) {     } } 


回答2:

You can add library trust manager that accepts all certificate instead of creating one.

FTPSClient mFtps = new FTPSClient(); mFtps.setTrustManager(TrustManagerUtils.getAcceptAllTrustManager()); 


回答3:

getAcceptAllTrustManager() means no checks are done regarding the validity of the certificates. May be ok if you have control end-to-end of the sites involved. See: Trusting all certificates using HttpClient over HTTPS



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!