1. 概述
与远程服务器交互是现代软件开发和系统管理中的常见任务,使用SSH客户端与远程服务器进行编程交互允许部署应用程序、管理配置、传输文件等。JSch、Apache MinaSSHD和SSHJ库是Java中流行的SSH客户端。
在本教程中,我们将学习如何使用JSch、Apache Mina SSHD和SSHJ库与远程服务器交互。此外,我们将了解如何使用私钥建立与远程服务器的连接,并列出服务器中特定目录中的所有文件夹。
2. 使用JSch库
JSch(Java安全通道)库提供用于与SSH服务器建立连接的类,它是SSH2的Java实现。
首先,让我们将JSch依赖添加到pom.xml中:
<dependency>
<groupId>com.github.mwiede</groupId>
<artifactId>jsch</artifactId>
<version>0.2.18</version>
</dependency>
接下来,让我们定义连接详细信息以建立与远程服务器的连接:
private static final String HOST = "HOST_NAME";
private static final String USER = "USERNAME";
private static final String PRIVATE_KEY = "PRIVATE_KEY";
private static final int PORT = 22;
private static final String REMOTE_DIR = "REMOTE_DIR";
在这里,我们定义主机、用户和身份验证密钥的路径。此外,我们还定义端口和我们打算列出其文件夹的远程目录。
接下来,让我们创建一个JSch对象并添加PRIVATE_KEY用于身份验证:
JSch jsch = new JSch();
jsch.addIdentity(PRIVATE_KEY);
然后,让我们创建一个会话并连接到远程服务器:
Session session = jsch.getSession(USER, HOST, PORT);
session.setConfig("StrictHostKeyChecking", "no");
session.connect();
Session对象允许我们创建一个新的SSH会话。为简单起见,我们禁用严格主机密钥检查。
此外,让我们通过建立的SSH连接打开一个SFTP通道:
ChannelSftp channelSftp = (ChannelSftp) session.openChannel("sftp");
channelSftp.connect();
这里,我们在已建立的会话上创建了一个安全的文件传输协议,ChannelSftp对象允许我们从远程服务器上传、下载、列出等。
2.1 详细文件列表
现在我们已经打开了SFTP通道,让我们检索指定远程目录中的文件列表:
Vector<ChannelSftp.LsEntry> files = channelSftp.ls(REMOTE_DIR);
for (ChannelSftp.LsEntry entry : files) {
LOGGER.info(entry.getLongname());
}
在上面的代码中,我们调用ChannelSftp对象上的ls()方法,该方法返回ChannelSftp.LsEntry对象的Vector,每个对象代表一个文件或目录。然后,我们循环遍历文件和目录列表并记录每个文件或目录的长名称。getLongname()方法包含其他详细信息,例如权限、所有者、组和大小。
2.2 仅文件名
如果我们只对文件名感兴趣,我们可以调用ChannelSftp.LsEntry对象上的getFilename()方法:
Vector<ChannelSftp.LsEntry> files = channelSftp.ls(REMOTE_DIR);
for (ChannelSftp.LsEntry entry : files) {
LOGGER.info(entry.getFilename());
}
值得注意的是,操作成功后我们必须关闭SSH会话和SFTP通道:
channelSftp.disconnect();
session.disconnect();
本质上,关闭连接有助于释放资源。
3. 使用Apache Mina SSHD库
Apache Mina SSHD库旨在支持为客户端和服务器端提供SSH协议的Java应用程序。
我们可以执行多个SSH操作,如文件传输、部署等。要使用该库,让我们将sshd-core和sshd-sftp依赖项添加到pom.xml:
<dependency>
<groupId>org.apache.sshd</groupId>
<artifactId>sshd-core</artifactId>
<version>2.13.1</version>
</dependency>
<dependency>
<groupId>org.apache.sshd</groupId>
<artifactId>sshd-sftp</artifactId>
<version>2.13.1</version>
</dependency>
让我们维护上一节中使用的连接详细信息。首先,让我们启动SSH客户端:
try (SshClient client = SshClient.setUpDefaultClient()) {
client.start();
client.setServerKeyVerifier(AcceptAllServerKeyVerifier.INSTANCE);
// ...
}
接下来,让我们连接到SSH服务器:
try (ClientSession session = client.connect(USER, HOST, PORT).verify(10000).getSession()) {
FileKeyPairProvider fileKeyPairProvider = new FileKeyPairProvider(Paths.get(privateKey));
Iterable<KeyPair> keyPairs = fileKeyPairProvider.loadKeys(null);
for (KeyPair keyPair : keyPairs) {
session.addPublicKeyIdentity(keyPair);
}
session.auth().verify(10000);
}
在上面的代码中,我们使用身份验证凭据创建客户端会话。此外,我们使用FileKeyPairProvider对象加载私钥,由于私钥不需要密码,因此我们将null传递给loadKeys()方法。
3.1 详细文件列表
为了列出远程服务器上的文件夹,让我们创建一个SftpClientFactory对象来通过已建立的SSH会话打开SFTP通道:
SftpClientFactory factory = SftpClientFactory.instance();
接下来,让我们读取远程目录并获取目录条目的Iterable对象:
try (SftpClient sftp = factory.createSftpClient(session)) {
Iterable<SftpClient.DirEntry> entriesIterable = sftp.readDir(REMOTE_DIR);
List<SftpClient.DirEntry> entries = StreamSupport.stream(entriesIterable.spliterator(), false)
.collect(Collectors.toList());
for (SftpClient.DirEntry entry : entries) {
LOGGER.info(entry.getLongFilename());
}
}
在这里,我们读取远程目录并获取目录条目的Iterable,并将其转换为List,然后我们将长文件名记录到控制台。由于我们使用try-with-resources块,因此我们不需要明确关闭会话。
3.2 仅文件名
但是,为了仅获取文件名,我们可以对目录条目使用getFilename()方法,而不是getLongFileName():
for (SftpClient.DirEntry entry : entries) {
LOGGER.info(entry.getFilename());
}
getFilename()消除了其他文件信息并仅记录文件名。
4. 使用SSHJ库
SSHJ库也是一个Java库,它提供用于连接远程服务器并与之交互的类。要使用该库,让我们将其依赖添加到pom.xml中:
<dependency>
<groupId>com.hierynomus</groupId>
<artifactId>sshj</artifactId>
<version>0.38.0</version>
</dependency>
另外,让我们保留前面部分使用的连接详细信息。
让我们创建一个SSHClient对象来建立与远程服务器的连接:
try (SSHClient sshClient = new SSHClient()) {
sshClient.addHostKeyVerifier(new PromiscuousVerifier());
sshClient.connect(HOST);
sshClient.authPublickey(USER, PRIVATE_KEY);
// ...
}
然后,我们在已建立的SSH会话上建立一个SFTP通道:
try (SFTPClient sftpClient = sshClient.newSFTPClient()) {
List<RemoteResourceInfo> files = sftpClient.ls(REMOTE_DIR);
for (RemoteResourceInfo file : files) {
LOGGER.info("Filename: " + file.getName());
}
}
在上面的代码中,我们调用ls(),它接收sftpClient上的远程目录并将其存储为RemoteResourceInfo类型。然后我们循环遍历文件条目并将文件名记录到控制台。
最后,我们可以使用getAttributes()方法获取有关文件的更多详细信息:
LOGGER.info("Permissions: " + file.getAttributes().getPermissions());
LOGGER.info("Last Modification Time: " + file.getAttributes().getMtime());
在这里,我们通过调用getAttributes()方法上的getPermissions()和getMtime()方法进一步记录文件权限和修改时间。
5. 总结
在本文中,我们学习了如何使用JSch、Apache SSHD Mina和SSHJ库与远程服务器交互。此外,我们还了解了如何建立安全连接、使用私钥进行身份验证以及执行基本的文件操作。
Post Directory
