web-dev-qa-db-fra.com

SSH simple se connecter avec JSch

J'essaie de faire quelque chose à partir de cet exemple simple:

SSH, exécuter des commandes à distance avec Android

Je veux juste voir si je peux me connecter depuis mon téléphone Android à un serveur Linux en utilisant SSH, mais cela ne fonctionne pas ...

Voici mon code principal:

package com.example.ssh;

import Java.util.Properties;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
import Android.os.Bundle;
import Android.app.Activity;

 public class MainActivity extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    try
    {
        JSch jsch = new JSch();
          Session session = jsch.getSession("root","192.168.0.26", 22);
          session.setPassword("xxxxx");

          // Avoid asking for key confirmation
          Properties prop = new Properties();
          prop.put("StrictHostKeyChecking", "no");
          session.setConfig(prop);

          session.connect();

    }
    catch (Exception e)
    {
      System.out.println(e.getMessage());
    }
}
}

Qu'ai-je fait de mal ? Je n'ai aucun message d'erreur et je ne vois aucune connexion SSH sur mon Linux. J'ai ajouté les bibliothèques jsch et jzlib. Je n'ai aucun problème pour me connecter avec une session PuTTY.

EDIT1: En fait, j'ai trouvé une erreur qui explique pourquoi cela ne fonctionne pas, même si je ne sais pas comment résoudre le problème. L'erreur est:

Android.os.NetworkOnMainThreadException

cela semble donc vouloir dire que l'application ne peut pas effectuer d'opération de réseau sur son thread principal ...

14
Pozinux

Vous devez exécuter ce code dans un autre thread afin de ne pas bloquer le thread d'interface utilisateur, c'est ce que cette exception signifie. Si le thread d'interface utilisateur exécute un appel réseau, il ne peut pas repeindre l'interface utilisateur. Vos utilisateurs voient alors une interface utilisateur figée qui ne leur répond pas pendant que l'application attend l'appel du réseau pour se terminer. Android veut éviter de mauvaises expériences utilisateur comme celle-ci afin d'éviter de faire de telles choses en lançant cette exception.

Votre méthode onCreate () doit appeler un autre thread (je suggérerais d'utiliser une AsyncTask sur un thread brut) pour établir la connexion SSH. Ensuite, une fois terminé, il peut publier les résultats dans le thread d'interface utilisateur et mettre à jour en toute sécurité l'interface utilisateur de votre application à partir du thread d'interface utilisateur.

http://developer.Android.com/reference/Android/os/AsyncTask.html

17
chubbsondubs

la solution de chubbsondubs est parfaite. Je veux juste partager le code que j'ai créé pour ce problème aussi pour les gens qui veulent une solution rapide:

public class MainActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    new AsyncTask<Integer, Void, Void>(){
       @Override
       protected Void doInBackground(Integer... params) {
           try {
                 executeRemoteCommand("root", "myPW","192.168.0.26", 22);
           } catch (Exception e) {
                 e.printStackTrace();
           }
           return null;
       }
    }.execute(1);
}

public static String executeRemoteCommand(String username,String password,String hostname,int port)
        throws Exception {
    JSch jsch = new JSch();
    Session session = jsch.getSession(username, hostname, port);
    session.setPassword(password);

    // Avoid asking for key confirmation
    Properties prop = new Properties();
    prop.put("StrictHostKeyChecking", "no");
    session.setConfig(prop);

    session.connect();

    // SSH Channel
    ChannelExec channelssh = (ChannelExec)
            session.openChannel("exec");
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    channelssh.setOutputStream(baos);

    // Execute command
    channelssh.setCommand("lsusb > /home/pi/test.txt");
    channelssh.connect();
    channelssh.disconnect();

    return baos.toString();
}
15
Frange

A Kotlin solution:

import Android.os.AsyncTask
import Android.os.Bundle
import Android.support.v7.app.AppCompatActivity
import com.jcraft.jsch.ChannelExec
import com.jcraft.jsch.JSch
import Java.io.ByteArrayOutputStream
import Java.util.*

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        SshTask().execute()
    }

    class SshTask : AsyncTask<Void, Void, String>() {
        override fun doInBackground(vararg p0: Void?): String {
            val output = executeRemoteCommand("demo", "password", "test.rebex.net")
            print(output)
            return output
        }
    }
}

fun executeRemoteCommand(username: String,
                         password: String,
                         hostname: String,
                         port: Int = 22): String {
    val jsch = JSch()
    val session = jsch.getSession(username, hostname, port)
    session.setPassword(password)

    // Avoid asking for key confirmation.
    val properties = Properties()
    properties.put("StrictHostKeyChecking", "no")
    session.setConfig(properties)

    session.connect()

    // Create SSH Channel.
    val sshChannel = session.openChannel("exec") as ChannelExec
    val outputStream = ByteArrayOutputStream()
    sshChannel.outputStream = outputStream

    // Execute command.
    sshChannel.setCommand("ls")
    sshChannel.connect()

    // Sleep needed in order to wait long enough to get result back.
    Thread.sleep(1_000)
    sshChannel.disconnect()

    session.disconnect()

    return outputStream.toString()
}

Dans build.gradle ajouter:

dependencies {
    ...
    compile group: 'com.jcraft', name: 'jsch', version: '0.1.54'
}
1
phoenix