我被要求建立安全的 FTP 服务器连接。通过显式 TLS/SSL 的 FTP。为了实现这一点,我在现有的实现中添加了一行。这是我的 FTPClient 库 - it.sauronsoftware.ftp4j - 版本 1.6.1
ftpClient.setSecurity(FTPClient.SECURITY_FTPES);
//现有代码
ftpClient.setConnector(new HTTPTunnelConnector(proxyHost, proxyPort));
ftpClient.connect(getFtpHost(), getFtpPort());
ftpClient.login(getUsername(), getPassword());
ftpClient.setAutoNoopTimeout(30000);
当我在 JBOSS 5.1 上部署代码时,连接成功,但无法列出根目录中的文件。我们只有访问根目录的权限。
另一方面,我编写了一个独立的客户端(java 主程序)——通过它我可以打印 FTP 位置的文件,通过这种方式我确保了安全连接和 FTP 位置的文件可用性。在这里,我使用了
我的问题是,当我通过部署的应用程序建立安全连接时,我无法在远程位置找到任何文件。即:FTPFiles.length 为 0
非常感谢任何帮助,谢谢!
添加更多日志和信息, 未添加 FTPES 安全参数的正常流程(当前实现)
打印 ftpClient.serverStatus()
msg: Status of 'FTP Service'
msg: Connected from ec2-xyz
msg: Logged in as <user>
msg: TYPE: BINARY, STRUcture: File, Mode: Stream
msg: Total bytes transferred for session: 10511
msg: No data connection
msg: End of status
打印 ftpClient.serverStatus() 添加了 FTPES
msg: Status of 'FTP Service'
msg: Connected from ec2-xyz
msg: Logged in as <user>
msg: TYPE: ASCII, STRUcture: File, Mode: Stream
msg: No data connection
msg: End of status
我需要知道答案的几个问题(可能会导致修复):
- 在这里,TYPE: BINARY 已更改为 ASCII,谁能告诉我如何修改回 BINARY?请注意,没有进行明确的设置,在设置 FTPES 后进行了更改
- 此问题是否与代理/端口有关。如果是这样 - 我将无法提供这些信息。
- 截至目前,我正在使用应用程序中使用的相同代理进行测试。
- 是否需要导入任何证书才能查看/下载文件。
- 在网上找到这个与我的问题完全相同,http://www.proftpd.org/docs/howto/TLS.html (搜索 -“我可以使用 FTPS 登录,但我看不到任何目录。为什么不呢?”)但我需要解释我的第三方以进行所需的更改......我应该告诉什么?
独立客户端代码
import it.sauronsoftware.ftp4j.*;
import javax.net.ssl.*;
import java.io.File;
import java.security.*;
import java.util.List;
public class FTPWithSSL {
private static FTPClient ftpClient;
private static FTPConfig ftpConfig;
private DailyFTPConfig config;
public static void main(String args[]) throws Exception {
ftpConfig = new FTPConfig("username", "password", "FTPServer.net", 21, setupConnector());
FTPDownloader ftpDownloader = new FTPDownloader(ftpConfig, new FTPDownloadController() {
@Override
public List<FTPFile> download(FTPClient ftpClient) throws Exception {
downloadFile(ftpClient);
System.out.println("download success");
return null;
}
});
try {
openConnection();
List<FTPFile> ftpFileList = ftpDownloader.download();
closeConnection();
} catch (Exception e) {
e.printStackTrace();
}
}
private static void openConnection() throws Exception {
System.out.println("OpenConnection method");
if (ftpClient == null) {
ftpClient = new FTPClient();
// Even if the below line is commented, the code works fine
ftpClient.setSSLSocketFactory(getSSLSocketFactory());
System.out.println("setting FTPES here");
ftpClient.setSecurity(FTPClient.SECURITY_FTPES);
ftpClient.setConnector(ftpConfig.getConnector());
ftpClient.connect(ftpConfig.getFtpHost(), ftpConfig.getFtpPort());
ftpClient.login(ftpConfig.getUsername(), ftpConfig.getPassword());
ftpClient.setAutoNoopTimeout(30000);
System.out.println("ftpClient.isConnected() " + ftpClient.isConnected());
}
}
private static SSLSocketFactory getSSLSocketFactory() throws Exception {
TrustManager[] trustManager = new TrustManager[] { new X509TrustManager() {
public X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(X509Certificate[] certs, String authType) {
}
public void checkServerTrusted(X509Certificate[] certs, String authType) {
}
} };
SSLContext sslContext = null;
try {
sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, trustManager, new SecureRandom());
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (KeyManagementException e) {
e.printStackTrace();
}
SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
return sslSocketFactory;
}
private static void closeConnection() throws Exception {
System.out.println("ftpClient.serverStatus() -- ");
for (String serverStatus : ftpClient.serverStatus()) {
System.out.println(" msg: " + serverStatus);
}
if (ftpClient != null && ftpClient.isConnected()) {
ftpClient.disconnect(false);
}
}
private static void downloadFile(FTPClient ftpClient) throws Exception {
System.out.println("ftpsClient.currentDirectory() " + ftpClient.currentDirectory());
FTPFile[] ftpFile = ftpClient.list();
System.out.println("Name " + ftpFile[0].getName());
System.out.println("Link " + ftpFile[0].getLink());
System.out.println("Modified Date " + ftpFile[0].getModifiedDate());
String[] listnames = ftpClient.listNames();
System.out.println("ftpsClient.listNames() " +listnames);
System.out.println("ftpsClient.currentDirectory() " + ftpClient.list());
File file = new File( "C:\\opt\\copycat\\a1234.zip");
System.out.println("Downloading File: [" + file.getName() + "] has started.");
ftpClient.download("a1234.zip", file);
System.out.println("Downloading File: has Completed");
}
private static FTPConnector setupConnector() {
FTPConnector connector = new DirectConnector();
String proxyHost = "amazonaws.com";
if (proxyHost != null) {
System.out.println("proxy host NOT NULL");
int proxyPort = Integer.parseInt("123");
connector = new HTTPTunnelConnector(proxyHost, proxyPort);
}
return connector;
}
}
最佳答案
最后,我能够建立安全连接并能够使用 FTPES(通过显式 TLS/SSL 的 FTP)从 FTP 服务器下载最新文件。 在实际实现中,我只更改了 2 行代码(如下)。之前它有 list() 方法从 FTP 服务器获取文件,它的返回类型是 FTPFile[]
这是我所做的代码更改,其他行代码被修改/删除。
ftpClient.setSecurity(FTPClient.SECURITY_FTPES);
// get the FTP connection
String[] fileNames = ftpClient.listNames();
// Exisitng implementation
FTPFile[] ftpFiles = ftpClient.list("*.zip");
// after that there is an implementation for getting the latest files using the Comparator<FTPFile>
LIST 命令的输出有问题,即:LIST *.zip 没有给出正确的输出(我猜)
关于java - 通过显式 SSL/TLS 在 FTP 上登录成功但无法浏览文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50340857/