我正在尝试设置一个简单的 SSH 客户端,该客户端使用 Apache Mina SSHD 通过已知主机文件验证服务器的公钥。我在下面拼凑出可行的伪代码 - 好吧,如果我知道如何让客户端等待服务器主机密钥验证完成,它就会起作用。
import java.io.IOException;
import java.net.SocketAddress;
import java.nio.file.*;
import java.security.PublicKey;
import java.util.concurrent.TimeUnit;
import org.apache.sshd.client.SshClient;
import org.apache.sshd.client.config.hosts.KnownHostEntry;
import org.apache.sshd.client.future.*;
import org.apache.sshd.client.keyverifier.*;
import org.apache.sshd.client.session.ClientSession;
public class SshdTest {
public static void main(String[] args) throws IOException {
Path knownHostsPath = Paths.get(System.getProperty("user.home"), ".ssh", "known_hosts");
SshClient ssh = SshClient.setUpDefaultClient();
KnownHostsServerKeyVerifier verifier = new DefaultKnownHostsServerKeyVerifier(new ServerKeyVerifier() {
@Override
public boolean verifyServerKey(ClientSession cs, SocketAddress sa, PublicKey pk) {
return true; // ask user to verify unknown public key
}
}, true, knownHostsPath);
verifier.setModifiedServerKeyAcceptor(new ModifiedServerKeyAcceptor() {
@Override
public boolean acceptModifiedServerKey(ClientSession cs, SocketAddress sa, KnownHostEntry khe, PublicKey expected, PublicKey actual) throws Exception {
return true; // ask user to verify public key change
}
});
ssh.setServerKeyVerifier(verifier);
ssh.start();
String host = "localhost";
String username = "user";
int port = 22;
String password = "password";
ConnectFuture cf = ssh.connect(username, host, port).verify(5L, TimeUnit.SECONDS);
cf.await();
// wait for server hostkey verification to complete and check ok?
try (
ClientSession session = cf.getSession()) {
session.addPasswordIdentity(password);
AuthFuture auth = session.auth();
auth.await(5L, TimeUnit.SECONDS);
// check ok and do the work
}
ssh.stop();
}
}
我希望cf.await()
行包含连接和主机密钥验证过程,但它没有,这意味着用户被要求同时验证密码和主机密钥,或者如果代码保持不变,则以某种未定义的顺序。
如何让客户端在尝试其他任何操作(例如用户身份验证)之前等待服务器主机密钥验证完成?另外,如何检查验证是否成功?