java - JSch - 如何让用户确认主机指纹?

标签 java android security ssh jsch

在 Android 应用程序中,我尝试使用 JSch 库连接到 SSH 服务器。远程服务器是用户指定的,所以我事先不知道远程指纹。同时,我不想将 StrictHostKeyChecking 设置为 no,正如我在很多示例中看​​到的那样。

我想获取远程服务器指纹,并将其显示给用户接受。使用 JSch 或常规 Java,也许使用套接字,这可能吗?

这是一个您可以尝试的示例,只需将其粘贴到 Android Activity 的 onCreate 中即可:

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();

最佳答案

好的,我找到了一种方法来做到这一点。这可能不是最好的方式,但它是一种方式。使用 UserInfo.promptYesNo 需要 looping at the expense of CPU在等待用户响应或 Executor/FutureTask/BlockingQueue 的开销时。相反,执行连接的异步线程(因为网络任务不能在 UI 线程上发生)更有利于执行两次 - 一次“中断”并让用户接受,第二次成功。我想这就是“Android 方式”。为此,主机 key 需要存储在某个地方。假设我将它存储在 Android 的 PreferenceManager 中,然后从那里开始获取 key ,如果不可用则默认为空

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。在那里, session 有一个可用的 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,但这次将主机 key 添加到 JSch 的主机 key 存储库中。

关于java - JSch - 如何让用户确认主机指纹?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43646043/

相关文章:

java - JPanel 上没有出现或移动框..Java

java - Vert.x:记录到文件的最佳方式

java - 对多数据类型字符串进行排序

android - 在 android studio 中使用 MPAndroidChart

PHP-hash_pbkdf2 函数

security - 为什么色情网站会出现在我的 Google Analytics(分析)数据中?

java - 使用字段从 Directory API 获取部分响应

android - 有什么方法可以将 vimeo 视频链接到 Android 上的 native 播放器?

外部可访问的 Tomcat Manager 中的安全风险

android - 仅在 Android Oreo 中显示圆形箭头的进度对话框