GVKun编程网logo

使用org.apache.commons.net.ftp.FTPClient保护FTP(ftp怎么保护用户名密码)

23

在本文中,我们将带你了解使用org.apache.commons.net.ftp.FTPClient保护FTP在这篇文章中,我们将为您详细介绍使用org.apache.commons.net.ftp.

在本文中,我们将带你了解使用org.apache.commons.net.ftp.FTPClient保护FTP在这篇文章中,我们将为您详细介绍使用org.apache.commons.net.ftp.FTPClient保护FTP的方方面面,并解答ftp怎么保护用户名密码常见的疑惑,同时我们还将给您一些技巧,以帮助您实现更有效的Apache Commons FTPClient.listFiles、Apache Commons FTPClient挂起、Apache Commons Net FTPClient和listFiles()、apache-commons commons-pool2整合 commons-net 自定 FTPClient对象池

本文目录一览:

使用org.apache.commons.net.ftp.FTPClient保护FTP(ftp怎么保护用户名密码)

使用org.apache.commons.net.ftp.FTPClient保护FTP(ftp怎么保护用户名密码)

有什么办法可以实现安全的FTP org.apache.commons.net.ftp.FTPClient

如果没有,那么Java还有哪些其他选择?

答案1

小编典典

您可以使用org.apache.commons.net.ftp。 FTPSClient,
而不是org.apache.commons.net.ftp。 FTPClient 具有安全的ftp
http://commons.apache.org/proper/commons-
net/apidocs/org/apache/commons/net/ftp/FTPSClient.html

Apache Commons FTPClient.listFiles

Apache Commons FTPClient.listFiles

org.apache.commons.net.ftp.FTPClient在一个应用程序中使用FTP服务器。我能够connect,login,pwd和cwd。但是,当我尝试list文件时,它不会返回该目录中的文件列表,我肯定知道该目录中有文件。我正在使用方法FTPFile[] listFiles(),它返回的空数组FTPFile。

请在我正在尝试的代码段下面找到:

        String hostname = properties.getProperty("FTP_SERVER");
        String user = properties.getProperty("FTP_USER");
        String passwd = properties.getProperty("FTP_PASSWD");
        FTPClient client = new FTPClient();
        client.connect(hostname);
        client.login(user,passwd);
        String reply = client.getStatus();
        System.out.println(reply);
        client.enterRemotePassiveMode();
        client.changeWorkingDirectory("/uploads");
        FTPFile[] files = client.listFiles();
        System.out.println(files.length);
        for (FTPFile file : files) {
            System.out.println(file.getName());
        }

        String[] fileNames = client.listNames();
        if (fileNames != null) {
            for (String file : fileNames) {
                System.out.println(file);
            }
        }
        client.disconnect();

Apache Commons FTPClient挂起

Apache Commons FTPClient挂起

我们使用以下Apache Commons Net FTP代码连接到FTP服务器,轮询某些目录中的文件,如果找到文件,则将它们检索到本地计算机:

try {logger.trace("Attempting to connect to server...");// Connect to serverFTPClient ftpClient = new FTPClient();ftpClient.setConnectTimeout(20000);ftpClient.connect("my-server-host-name");ftpClient.login("myUser", "myPswd");ftpClient.changeWorkingDirectory("/loadables/");// Check for failed connectionif(!FTPReply.isPositiveCompletion(ftpClient.getReplyCode())){    ftpClient.disconnect();    throw new FTPConnectionClosedException("Unable to connect to FTP server.");}// Log success msglogger.trace("...connection was successful.");// Change to the loadables/ directory where we poll for filesftpClient.changeWorkingDirectory("/loadables/");// Indicate we''re about to polllogger.trace("About to check loadables/ for files...");// Poll for files.FTPFile[] filesList = oFTP.listFiles();for(FTPFile tmpFile : filesList){    if(tmpFile.isDirectory())        continue;    FileOutputStream fileOut = new FileOutputStream(new File("tmp"));    ftpClient.retrieveFile(tmpFile.getName(), fileOut);    // ... Doing a bunch of things with output stream    // to copy the contents of the file down to the local    // machine. Ommitted for brevity but I assure you this    // works (except when the WAR decides to hang).    //    // This was used because FTPClient doesn''t appear to GET    // whole copies of the files, only FTPFiles which seem like    // file metadata...}// Indicate file fetch completed.logger.trace("File fetch completed.");// Disconnect and finish.if(ftpClient.isConnected())    ftpClient.disconnect();logger.trace("Poll completed.");} catch(Throwable t) {    logger.trace("Error: " + t.getMessage());}

我们计划将其每分钟运行一次。当部署到Tomcat(7.0.19)时,此代码可以很好地加载并开始正常运行。但是,每次似乎都在 挂起 。我的意思是:

  • 不存在堆转储
  • Tomcat仍在运行(我可以看到其pid并可以登录到Web Manager应用程序)
  • 在管理器应用程序中,我可以看到我的WAR仍在运行/启动
  • catalina.out 而且我的应用程序专用日志没有任何异常抛出的迹象

因此,JVM仍在运行。Tomcat仍在运行,而我部署的WAR仍在运行,但是它刚刚挂起。有时它会运行2个小时,然后挂起。有时它会运行几天然后挂起。但是当它挂起时,它会在读取的行Aboutto check loadables/ for files...(我确实在日志中看到)和读取的行File fetchcompleted.(我没有看到)之间这样做。

这告诉我挂起发生在实际轮询/获取文件的过程中,这种情况使我指出了与该问题相同的方向,这个问题使我能够找到与FTPClient死锁有关的问题。这让我想知道这些是否是相同的问题( 如果是的话,我会很乐意删除此问题!
)。不过,我不认为 认为 它们是相同的(我没有看到我日志中的同样的例外)。

一位同事提到这可能是“被动”与“主动”
FTP的问题。没有真正知道的区别,我由FTPClient领域糊涂一点ACTIVE_REMOTE_DATA_CONNECTION_MODEPASSIVE_REMOTE_DATA_CONNECTION_MODE等等,不知道为什么情绪这么想过,作为一个潜在的问题。

由于我在Throwable这里是不得已而为之的方法,因此,如果出现问题,我本可以期望在日志中看到 某些内容 。嗯,我觉得这绝对是个难题。

有任何想法吗?不幸的是,我对FTP的内部知识了解不足,无法做出可靠的诊断。这可能是服务器端的东西吗?与FTP服务器相关?

答案1

小编典典

这可能有很多事情,但是您朋友的建议是值得的。

尝试ftpClient.enterLocalPassiveMode();看看是否有帮助。

我还建议 将断开连接放在finally块中,以使其永远不会留下连接。

Apache Commons Net FTPClient和listFiles()

Apache Commons Net FTPClient和listFiles()

谁能解释以下代码有什么问题?我尝试了其他主机FTPClientConfigs,可以通过firefox /
filezilla正确访问它。问题是我总是得到空的文件列表,没有任何异常(files.length == 0)。我使用随Maven安装的commons-
net-2.1.jar。

    FTPClientConfig config = new FTPClientConfig(FTPClientConfig.SYST_L8);    FTPClient client = new FTPClient();    client.configure(config);    client.connect("c64.rulez.org");    client.login("anonymous", "anonymous");    client.enterRemotePassiveMode();    FTPFile[] files = client.listFiles();    Assert.assertTrue(files.length > 0);

答案1

小编典典

找到了!

问题是您想 在连接之后但在登录之前进入被动模式 。您的代码对我没有任何回报,但这对我有用:

import org.apache.commons.net.ftp.FTPClient;import java.io.IOException;import org.apache.commons.net.ftp.FTPFile;public class BasicFTP {    public static void main(String[] args) throws IOException {        FTPClient client = new FTPClient();        client.connect("c64.rulez.org");        client.enterLocalPassiveMode();        client.login("anonymous", "");        FTPFile[] files = client.listFiles("/pub");        for (FTPFile file : files) {            System.out.println(file.getName());        }    }}

给我这个输出:

c128c64c64.hu传入加4

apache-commons commons-pool2整合 commons-net 自定 FTPClient对象池

apache-commons commons-pool2整合 commons-net 自定 FTPClient对象池

commons-net 包介绍

commons-net 是 apachecommons 用于网络的工具包,它实现了一些常见的网络工具,如 smtppop3telnetftpudp 等,本文主要使用它的 ftp 工具。

使用 FTP 工具时的问题

在使用 commons-net 提供的 ftp 工具的时候 ,发现每次都要走一遍完整的连接,登录流程。每次都创建连接的话,很快就会把连接耗光,如果使用单例,则效率过低,因为只有一个连接,所以考虑用对象池的方式。

自已定义对象池的话,我之前有弄过,但要考虑好多的问题。像线程池一样,需要考虑核心对象数、最大对象数、何时创建对象 、及队列等,这时可以使用 apache 的 commons-pool2 来做一个对象池。

重要说明 : FTPClient 每次使用都需要重新连接,不然它会自动断开连接,使用会直接返回 421 ,本文章只是给个使用 commons-pool2 对象池的示例。

如何使用 commons-pool2

可以这么想,如果我要做个对象池的工具给别人用,首先要考虑的是池子里装的什么,用户要如何创建池子里的对象,然后提供方法借对象和回收对象,我可以把池子中的对象抽象出来,由一个工厂统一管理,用户的对象从我的通用对象继承或实现,或使用聚合方式 。

其实 spring-data-redis 已经给我们一个完整的使用 commons-pool2 的例子,它就是用的 commons-pool2 ,它的池中对象是 redis 连接,有兴趣可以去瞧瞧。

定义池中对象 FTPClient 的扩展对象

因为 FTPClient 的功能太过简单,连多层目录时自己创建目录都不会,所以有必要给它包装一下,这里你可以扩展常用到的方法。

import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;

@Slf4j
public class FtpClientExtend {
    private FTPClient ftpClient ;

    public FtpClientExtend(FTPClient ftpClient) {
        this.ftpClient = ftpClient;
    }

    /**
     * 列出文件列表
     * @param filePath
     * @return
     * @throws IOException
     */
    public FTPFile[] listFiles(String filePath) throws IOException {
        return ftpClient.listFiles(filePath);
    }

    /**
     * 下载文件
     * @param filePath
     * @return
     */
    public InputStream downloadFile(String filePath) throws IOException {
        return ftpClient.retrieveFileStream(filePath);
    }

    /**
     * 存储文件
     * @param s
     * @param inputStream
     */
    public void uploadFile(String filePath, InputStream inputStream) throws IOException {
        File targetFilePath = new File(filePath);
        Path path = targetFilePath.getParentFile().toPath();
        Iterator<Path> iterator = path.iterator();
        StringBuffer root = new StringBuffer("");
        while (iterator.hasNext()){
            Path next = iterator.next();
            root.append("/").append(next);

            //尝试切入目录
            boolean success = ftpClient.changeWorkingDirectory(root.toString());
            if(!success){
                int mkd = ftpClient.mkd(next.toString());
                ftpClient.changeWorkingDirectory(root.toString());
            }
        }

        ftpClient.enterLocalPassiveMode();
        ftpClient.setControlEncoding("UTF-8");
        ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
        boolean storeFileResult = ftpClient.storeFile(targetFilePath.getName(), inputStream);
        if (storeFileResult) {
            log.debug("上传文件:" + filePath + ",到目录:" + ftpClient.printWorkingDirectory() + " 成功");
        }else{
            log.debug("上传文件:" + filePath + ",到目录:" + ftpClient.printWorkingDirectory() + " 失败");
        }
    }
}

使用聚合包裹池中对象

这个包裹对象的类才是工厂真正产生在池中的类,文末给出图示

import org.apache.commons.pool2.PooledObjectFactory;
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;

public class FtpClientPool extends GenericObjectPool<FtpClientExtend> {

    public FtpClientPool(PooledObjectFactory<FtpClientExtend> factory) {
        super(factory);
    }

    public FtpClientPool(PooledObjectFactory<FtpClientExtend> factory, GenericObjectPoolConfig config) {
        super(factory, config);
    }
}

建立创建对象的工厂

import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.pool2.BasePooledObjectFactory;
import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.impl.DefaultPooledObject;

public class FtpClientFactory extends BasePooledObjectFactory<FtpClientExtend> {
    @Value("${ftp.host:localhost}")
    private String host;
    @Value("${ftp.port:21}")
    private int port;
    @Value("${ftp.username:ftpadmin}")
    private String username;
    @Value("${ftp.password:salt202}")
    private String password;

    @Override
    public FtpClientExtend create() throws Exception {
        FTPClient ftpClient = new FTPClient();
        ftpClient.connect(host,port);
        boolean login = ftpClient.login(username, password);
        if(!login){
            throw new RuntimeException("ftp 登录失败,检查用户名密码是否正确["+host+":"+port+"]["+username+"]["+password+"]");
        }
        return new FtpClientExtend(ftpClient);
    }

    @Override
    public PooledObject<FtpClientExtend> wrap(FtpClientExtend ftpClientExtend) {
        return new DefaultPooledObject(ftpClientExtend);
    }
}

使用方法

@Autowired
private FtpClientPool ftpClientPool;

public void method(){
    FtpClientExtend ftpClientExtend = null;
    try{
        ftpClientExtend = ftpClientPool.borrowObject();
    }finally{
         if(ftpClientExtend != null) {
          ftpClientPool.returnObject(ftpClientExtend);
        }
    }
}

原理图示

在这里插入图片描述

今天的关于使用org.apache.commons.net.ftp.FTPClient保护FTPftp怎么保护用户名密码的分享已经结束,谢谢您的关注,如果想了解更多关于Apache Commons FTPClient.listFiles、Apache Commons FTPClient挂起、Apache Commons Net FTPClient和listFiles()、apache-commons commons-pool2整合 commons-net 自定 FTPClient对象池的相关知识,请在本站进行查询。

本文标签: