当前位置: 首页 > 工具软件 > Commons-VFS > 使用案例 >

比较中的Commons VFS,SSHJ和JSch

呼延烈
2023-12-01

几周前,我评估了一些用于Java的SSH库。 对它们的主要要求是在远程计算机上进行文件传输和文件操作。 因此,它存在一个基于SSH,SSH文件传输协议(或SFTP)的网络协议。 因此,我需要一个支持SFTP的SSH库。

一项研究表明,它退出了许多用于Java的SSH库。 为了进行比较,我将库的数量减少到三个。 我选择JSch,SSHJ和Apache的Commons VFS,以获得更深入的了解。 它们都支持SFTP。 JSch似乎是Java的实际标准。 SSHJ是较新的库。 其目标是为SSH提供一个清晰的Java API。 它在后台使用Apache SSHD。 Commons VFS的目标是为虚拟文件系统提供清晰的API,SFTP是受支持的协议之一。 在后台,它将JSch用于SFTP协议。 这些库应满足以下要求:

  • 通过密码进行客户端身份验证
  • 通过公钥进行客户端身份验证
  • 服务器认证
  • 通过SFTP从本地主机上传文件
  • 通过SFTP将文件下载到本地主机
  • 远程主机上的文件操作,例如通过SFTP移动,删除,列出给定文件夹的所有子文件夹(在文件或文件夹等类型之后进行过滤)
  • 执行普通的shell命令

让我们更深入地了解这三个库如何满足需求。

客户端认证

这三个库都支持两种必需的身份验证方法。 SSHJ具有最清晰的身份验证API( SSHClient.authUserPass(),SSHClient.authUserPublicKey() )。

SSHClient sshClient= new SSHClient();
sshClient.connect(host);

// only for public key authentication
sshClient.authPublickey("user", "location to private key file");

// only for password authentication
sshClient.authPassword("user", "password");

在Commons VFS中,身份验证配置取决于应使用哪种身份验证。 对于公共密钥身份验证,必须在FileSystemOption中设置私有密钥,并且用户名是连接URL的一部分。 对于密码验证,用户名和密码是连接URL的一部分。

StandardFileSystemManager fileSystemManager = new StandardFileSystemManager();
fileSystemManager.init();

// only for public key authentication
SftpFileSystemConfigBuilder sftpConfigBuilder = SftpFileSystemConfigBuilder.getInstance();
FileSystemOptions opts = new FileSystemOptions();
sftpConfigBuilder.setIdentities(opts, new File[]{privateKey.toFile()});
String connectionUrl = String.format("sftp://%s@%s", user, host);

// only for password authentication
String connectionUrl = String.format("sftp://%s:%s@%s", user, password, host);

// Connection set-up
FileObject remoteRootDirectory = fileSystemManager.resolveFile(connectionUrl, connectionOptions);

JSch中的认证配置类似于Commons VFS。 这取决于应使用哪种身份验证。 必须在JSch对象中配置用于公共密钥认证的私钥,并且必须在Session对象中设置用于密码认证的密码。 对于两者,当JSch对象获取Session对象时,将设置用户名。

JSch sshClient = new JSch();

// only for public key authentication
sshClient.addIdentity("location to private key file");

session = sshClient.getSession(user, host);

// only for password authentication
session.setPassword(password);

session.connect();

服务器认证

这三个库均支持服务器身份验证。 在SSHJ中,可以使用SSHClient.loadKnownHost启用服务器身份验证。 可以添加自己的known_host文件位置,也可以使用默认位置,该位置取决于使用平台。

SSHClient sshClient = new SSHClient();
sshClient.loadKnownHosts(); // or sshClient.loadKnownHosts(knownHosts.toFile());
sshClient.connect(host);

在Commons VFS中,服务器身份验证配置也是FileSystemOption的一部分,类似于公钥身份验证。 在那里,可以设置known_hosts文件的位置。

SftpFileSystemConfigBuilder sftpConfigBuilder = SftpFileSystemConfigBuilder.getInstance();
FileSystemOptions opts = new FileSystemOptions();
sftpConfigBuilder.setKnownHosts(opts, new File("location of the known_hosts file"));

在JSch中,存在两种配置服务器身份验证的可能性。 一种可能性是使用OpenSSHConfig (请参阅JSch示例以了解OpenSSHConfig )。 另一种可能性更容易。 可以直接在JSch对象中设置known_hosts文件的位置。

JSch sshClient = new JSch();
sshClient.setKnownHosts("location of known-hosts file");

通过SFTP上传/下载文件

这三个库均支持通过SFTP上传和下载文件。 SSHJ具有非常清晰的API用于这些操作。 SSHClient对象创建一个SFTPClient对象。 这个对象负责上传(SFTPClient。PUT)和下载(SFTPClient。 获得 )。

SSHClient sshClient = new SSHClient();
// ... connection

try (SFTPClient sftpClient = sshClient.newSFTPClient()) {
  // download
  sftpClient.get(remotePath, new FileSystemFile(local.toFile()));
  // upload
  sftpClient.put(new FileSystemFile(local.toFile()), remotePath);
}

在Commons VFS中,上传和下载文件被抽象为在文件系统上的操作。 因此,两者均由FileObject对象的copyFrom方法表示。 上传是参数】remotefile对象上的copyfrom操作和下载是在LOCALFILE一个的copyfrom操作

StandardFileSystemManager fileSystemManager = new StandardFileSystemManager();
// ... configuration
remoteRootDirectory = fileSystemManager.resolveFile(connectionUrl, connectionOptions);

LocalFile localFileObject = (LocalFile) fileSystemManager.resolveFile(local.toUri().toString());
FileObject remoteFileObject = remoteRootDirectory.resolveFile(remotePath);
try {
  // download
  localFileObject.copyFrom(remoteFileObject, new AllFileSelector());

  // upload
  remoteFileObject.copyFrom(localFileObject, new AllFileSelector());
} finally {
  localFileObject.close();
  remoteFileObject.close();
}

JSch还支持SFTPClient。 在JSch中,它称为ChannelSFTP 。 它有两种下载( ChannelSFTP.get )和上载( ChannelSFTP.put )的方法。

// here: creation and configuration of session

ChannelSftp sftpChannel = null;
try {
  sftpChannel = (ChannelSftp) session.openChannel("sftp");
  sftpChannel.connect();

  // download
  InputStream inputStream = sftpChannel.get(remotePath);
  Files.copy(inputStream, localPath);

  // upload
  OutputStream outputStream = sftpChannel.put(remotePath);
  Files.copy(locaPathl, outputStream);
} catch (SftpException | JSchException ex) {
  throw new IOException(ex);
} finally {
  if (sftpChannel != null) {
    sftpChannel.disconnect();
  }
}

执行Shell命令

仅Commons VFS不支持执行普通Shell命令。 在SSHJ中,它是两层的。 SshClient启动一个新的Session对象。 该对象执行shell命令。 这是非常直观的。

// creation and configuration of sshClient

try (Session session = sshClient.startSession()) {
  session.exec("ls");
}

在Jsch中, ChannelExec负责通过SSH执行Shell命令。 首先,在通道中设置命令,然后必须启动通道。 它不像SSHJ那样直观。

// here: creation and configuration of session object

ChannelExec execChannel = null;
try {
  execChannel = (ChannelExec) session.openChannel("exec");
  execChannel.connect();
  execChannel.setCommand(command);
  execChannel.start();
} catch (JSchException ex) {
  throw new IOException(ex);
} finally {
  if (execChannel != null) {
    execChannel.disconnect();
  }
}

远程主机上的文件操作

所有库都通过远程计算机上的SFTP支持或多或少的理想文件操作。 在SSHJ中, SFTPClient也具有用于文件操作的方法。 方法的名称与Linux系统上的文件操作相同。 以下代码段显示了如何删除文件。

//here: creation and configuration of sshClient

try (SFTPClient sftpClient = sshClient.newSFTPClient()) {
  sftpClient.rm(remotePath);
}

Commons VFS的核心功能是文件操作。 用法需要习惯。 必须解析文件对象,并且可以对其执行文件操作。

// here: creation and configuration of remoteRootDirectory

FileObject remoteFileObject = remoteRootDirectory.resolveFile(remotePath);
try {
  remoteFileObject.delete();
} finally {
  remoteFileObject.close();
}

JSch的SFTPClient ChannelSFTP也具有文件操作方法。 此通道支持大多数文件操作。 例如,必须通过ChannelExec上的简单外壳命令来完成远程计算机上的文件复制操作。

// here: creation and configuration of session
ChannelSftp sftpChannel = null;
try {
  sftpChannel = (ChannelSftp) session.openChannel("sftp");
  sftpChannel.connect();
  sftpChannel.rm(remotePath);
} catch (SftpException | JSchException ex) {
  throw new IOException(ex);
} finally {
  if (sftpChannel != null) {
    sftpChannel.disconnect();
  }
}

结论

比较之后,我有两个收藏夹,SSHJ和Commons VFS。 SSHJ具有非常清晰的API,如果我需要通用的SSH客户端或通过SFTP进行文件操作就足够了,我会选择它。 如果我可以通过许多文件系统协议进行文件操作,或者不需要通用的SSH客户端,则可以选择Commons VFS。 对于这两种情况,我可以同时使用JSch来通过SSH执行命令。 Commons VFS的API已经习惯了。 但是在了解了背后的概念之后,API的用法就很简单了。

这个比较的整个源代码示例都托管在Github上

有用的链接

  1. SSHJ主页
  2. JSch主页
  3. Commons-vfs主页
  4. 有关SFTP的维基百科页面
  5. SSHD主页
  6. Github上此比较的源代码

翻译自: https://www.javacodegeeks.com/2015/08/commons-vfs-sshj-and-jsch-in-comparison.html

 类似资料: