在Android应用中,我尝试使用JSch库连接到SSH服务器。远程服务器由用户指定,因此我事先不知道远程指纹。与此同时,我并不想将onCreate
设置为否,就像我在很多例子中看到的那样。
我想获取远程服务器指纹,将其显示给用户以供接受。这可能是使用JSch还是常规Java,也许是使用套接字?
以下是您可以尝试的示例,只需将其粘贴到Android活动的new Thread(new Runnable() {
@Override
public void run() {
com.jcraft.jsch.Session session;
JSch jsch;
try {
jsch = new JSch();
jsch.setLogger(new MyLogger());
session = jsch.getSession("git", "github.com", 22);
session.setPassword("hunter2");
Properties prop = new Properties();
prop.put("StrictHostKeyChecking", "yes");
session.setConfig(prop);
//**Get a host key and show it to the user**
session.connect(); // reject HostKey: github.com
}
catch (Exception e){
LOG.error("Could not JSCH", e);
}
}
}).start();
中即可:
Projects.detectProjectByKeyword("brumi")
答案 0 :(得分:3)
好的,我找到了办法。它可能不是最好的方式,但它是 a 方式。在等待用户响应时使用UserInfo.promptYesNo
所需looping at the expense of CPU或使用Executor / FutureTask / BlockingQueue的开销。相反,执行连接的异步线程(因为网络任务不能在UI线程上发生)更有利于两次这样做 - 一次到达' break'并让用户接受,第二个成功。我想这是Android的方式'。为此,hostkey需要存储在某处。假设我将它存储在Android的PreferenceManager中,然后从那里抓取密钥,默认为空,如果不可用
String keystring = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()).getString("target_hostkey","");
if(!Strings.isNullOrEmpty(keystring)){
byte[] key = Base64.decode ( keystring, Base64.DEFAULT );
jsch.getHostKeyRepository().add(new HostKey("github.com", key ), null);
}
接下来,像往常一样继续连接到服务器
session = jsch.getSession("git", "github.com", 22);
session.setPassword("hunter2");
Properties prop = new Properties();
prop.put("StrictHostKeyChecking", "yes");
session.setConfig(prop);
session.connect();
但这一次,赶上JSchException
。在那里,会话有一个HostKey可用。
catch(final JSchException jex){
LOG.debug(session.getHostKey().getKey());
final com.jcraft.jsch.Session finalSession = session;
runOnUiThread(new Runnable() {
@Override
public void run() {
new MaterialDialog.Builder(MyActivity.this)
.title("Accept this host with fingerprint?")
.negativeText(R.string.cancel)
.positiveText(R.string.ok)
.content(finalSession.getHostKey().getFingerPrint(jsch))
.onPositive(new MaterialDialog.SingleButtonCallback() {
@Override
public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
PreferenceManager.getDefaultSharedPreferences(getApplicationContext()).edit().putString("target_hostkey", finalSession.getHostKey().getKey()).apply();
}
}).show();
}
});
}
在此之后,重新调用Thread或AsyncTask是一个问题,但这次将hostkey添加到JSch的hostkey存储库中。
答案 1 :(得分:1)
两种可能性:
当StrictHostKeyChecking
设置为ask
时,JSch会在确认提示下调用UserInfo.promptYesNo
。实施UserInfo
interface以向用户显示确认。缺点是您无法以任何方式自定义消息(当然,除非您尝试解析它,依赖于硬编码模板)。
消息如下:
警告:远程主机识别已更改!
有可能是某人做的很棒! 有人可能正在偷听你(中间人攻击)! -key_type-主机密钥也可能刚刚更改 远程主机发送的-key_type-密钥的指纹为
-key_fprint-
请联系您的系统管理员 在-file-中添加正确的主机密钥以消除此消息。
有关示例实现,请参阅official JSch KnownHosts.java
example。
甚至在上述情况之前,JSch调用HostKeyRepository.check
,传递主机名和密钥。
您可以实现该接口/方法,以执行您喜欢的任何提示。
检查Session.checkHost
实施。