在我的第一个严肃项目的后期状态中,我对 Android 开发还很陌生。简而言之,该程序将 ssh 进入 Linux 主机并执行命令。但我发现自己在试图完成这件事时真的陷入了困境。
我正在使用 ganymed-ssh2 来做 ssh grunt-work。
当点击“活动”按钮时,我希望程序启动 SSH 会话,验证主机指纹 - 必要时提示接受,然后按程序发出远程命令。但这看似简单的几个步骤,却被以下变得非常复杂:
- ssh 无法在 UI 线程中执行,所以我必须启动一个 AsyncTask,所以我在接下来的麻烦中描述的所有内容都不在前台 UI 线程中。
要激活 ssh 指纹识别代码,我需要在我的 AsyncTask 类中进行这样的调用:
@Override protected String doInBackground(String... command) { String result; result = ""; try { /* Create a connection instance */ Connection conn = new Connection(connect.getHost(), connect.getPort()); /* Now connect */ ConnectionInfo info = conn.connect(new AdvancedVerifier()); boolean isAuthenticated = false; // first try public key if defined if (connect.getPrivateKey() != null) isAuthenticated = conn.authenticateWithPublicKey (connect.getUserid(), connect.getPrivateKey(), null); // if failed, or not defined, try password if provide if (!isAuthenticated && connect.getPassword() != null) isAuthenticated = conn.authenticateWithPassword(connect.getUserid(), new String (connect.getPassword())); // all else, get out if (!isAuthenticated) throw new IOException("Authentication failed."); /* Create a session */ Session sess = conn.openSession(); sess.execCommand(command[0]); }
但是,conn.connect(new AdvancedVerifier()) 行会导致调用 AdvancedVerifier 的回调接口类,从而在 connect 调用时中断执行路径以调用该类:
class AdvancedVerifier implements ServerHostKeyVerifier
{
public boolean verifyServerHostKey(String hostname, int port,
String serverHostKeyAlgorithm,
byte[] serverHostKey) throws Exception
{
final String host = hostname;
final String algo = serverHostKeyAlgorithm;
/* Check database - code removed*/
/* assuming fingerprint needs verification */
String hexFingerprint =
KnownHosts.createHexFingerprint(serverHostKeyAlgorithm,
serverHostKey);
String msg = "Hex Fingerprint: " + hexFingerprint;
/* right here, I need to display dialog of fingerprint,
and ask user for to continue;
If user accepts, return true, else return false.
If return true, the above class continues after connect(), if false
it is aborted.
*/
return UserAccepts? true : false;
}
}
好吧,以我有限的经验,这似乎引发了很多非常混乱的代码。首先,我需要重新连接到 UI 线程,显示一个对话框,然后如果用户选择 OK,然后从 verifyServerHostKey() 返回“true”,分离 UI 线程,并允许 ssh 连接代码恢复。所有这些都无法使用模式对话框。
坦率地说,我真的不知道从哪里开始,正在寻找想法、指导等。