如何在Android Pie上运行Apache-Mina SSHD服务器(2.2.0)?

时间:2019-05-01 10:37:15

标签: android apache apache-mina apache-sshd

我正在尝试在Android Pie(API 28.0)设备上运行Apache MINA SSHD服务器(v。2.2.0)。我发现有很多关于它在Android 4设备上运行的文章,但似乎都没有在我的Android 9设备上运行。因此,我尝试自己实现它,但是由于ReflectionException / NoClassDefFoundError陷入了服务器的初始化阶段。

当我尝试使用SshServer.setUpDefaultServer()设置服务器时;我收到此异常:

java.lang.NoClassDefFoundError: Failed resolution of: Ljavax/management/ReflectionException;
        at org.apache.sshd.common.util.GenericUtils.peelException(GenericUtils.java:730)
        at org.apache.sshd.common.util.GenericUtils.peelException(GenericUtils.java:728)
        at org.apache.sshd.common.util.security.SecurityEntityFactory$2.getInstance(SecurityEntityFactory.java:134)
        at org.apache.sshd.common.util.security.SecurityUtils.getMessageDigest(SecurityUtils.java:726)
        at org.apache.sshd.common.digest.DigestUtils.checkSupported(DigestUtils.java:53)
        at org.apache.sshd.common.digest.BuiltinDigests.<init>(BuiltinDigests.java:61)
        at org.apache.sshd.common.digest.BuiltinDigests.<clinit>(BuiltinDigests.java:36)
        at org.apache.sshd.common.cipher.ECCurves.<clinit>(ECCurves.java:61)
        at org.apache.sshd.common.keyprovider.KeyPairProvider.<clinit>(KeyPairProvider.java:63)
        at org.apache.sshd.common.signature.BuiltinSignatures.<clinit>(BuiltinSignatures.java:62)
        at org.apache.sshd.common.BaseBuilder.<clinit>(BaseBuilder.java:133)
        at org.apache.sshd.server.ServerBuilder.builder(ServerBuilder.java:165)
        at org.apache.sshd.server.SshServer.setUpDefaultServer(SshServer.java:429)
        at ch.zhaw.init.sshshell.SshShellService.<init>(SshShellService.java:20)

从Android 4的一些较旧的帖子中看来,这是一个已知问题,解决方案是将$ useLibrary'org.apache.http.legacy'添加到gradle并添加到manifest.xml中。我这样做了,但仍然发生了异常。

build.gradle文件:

android {
    compileSdkVersion 28
    useLibrary 'org.apache.http.legacy'
    ...
}
dependencies {
    ...
    implementation 'org.apache.sshd:sshd-core:2.2.0'
    implementation 'org.slf4j:slf4j-simple:1.6.2'
    implementation 'org.apache.mina:mina-core:2.1.2'
    implementation "org.bouncycastle:bcprov-jdk16:1.46"
}

manifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="ch.zhaw.init.sshshell">
    <application
            android:networkSecurityConfig="@xml/network_security_config">
        <uses-library android:name="org.apache.http.legacy"
                      android:required="false" />
        <service android:name=".SshShellService">
            <intent-filter>
                <action android:name="StartSshServer"/>
            </intent-filter>
        </service>
    </application>
</manifest>

我的Java代码:

import org.apache.sshd.server.SshServer;
import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider;


private static final int PORT = 8022;
private final SshServer sshd = SshServer.setUpDefaultServer(); // Here I get the error
private final SimplePasswordAuthenticator passwordAuth = new SimplePasswordAuthenticator();
private final SimplePublicKeyAuthenticator publicKeyAuth = new SimplePublicKeyAuthenticator();
private final SimpleForwardingFilter forwardingFilter = new SimpleForwardingFilter();

似乎旧版本有效,但我搜索了几天,却没有找到最新版本的有效示例。是否有人能在Android 9上运行最新版本的Apache Mina SSHD(2.2.0)的有效示例(无需生根设备)?

或者如果没有,则为Android Pie提供替代的SSH服务器(不是客户端-其中很多)?

谢谢您的帮助。

2 个答案:

答案 0 :(得分:0)

对于这种特定的失败,只需创建一个虚拟的ReflectionException类(example)。鉴于该类甚至不存在,您自己的代码之外的任何事都不会实例化它,因此SSHD的instanceof ReflectionException检查将永远不会匹配,并且您无需对任何其成员进行编程。

您还将要创建一个虚拟MBeanException (example)

答案 1 :(得分:0)

由于 BouncyCastle lib 导致的错误已被弃用为 android9(api 级别 28)。

您可以从 aosp 获取详细提示:http://androidxref.com/9.0.0_r3/xref/libcore/ojluni/src/main/java/sun/security/jca/Providers.java#548

https://android-developers.googleblog.com/2018/03/cryptography-changes-in-android-p.html

要解决这个问题,您可以按照以下步骤操作:

  1. 从系统默认卸载 BouncyCastleProvider
Security.removeProvider("BC");
  1. 安装新的“BC”自定义提供程序
Security.addProvider(new BouncyCastleProvider());
  1. 初始化你的 mina sshd 服务
 SshServer sshd = SshServer.setUpDefaultServer();
 sshd.setPort(ssdServerPort);
 ....

aosp 只是比较对象来决定 bc 提供者对象是否是系统默认提供者,所以只需用新的 bc 提供者对象替换 :http://androidxref.com/9.0.0_r3/xref/libcore/ojluni/src/main/java/sun/security/jca/Providers.java#341

注意:在安装提供程序之前,您必须使用 :Security.removeProvider("BC") 卸载提供程序