it-swarm.com.de

SSH-Bibliothek für Java

Kennt jemand eine gute Bibliothek für SSH-Login von Java.

181
rperez

Der Java Secure Channel (JSCH) ist eine sehr beliebte Bibliothek, die von Maven, Ant und Eclipse verwendet wird. Es ist Open Source mit einer BSD-Lizenz.

117

Update: Das GSOC-Projekt und der Code dort sind nicht aktiv, aber dies ist: https://github.com/hierynomus/sshj

hierynomus hat seit Anfang 2015 die Funktion des Betreuers übernommen. Hier der ältere, nicht mehr gepflegte Github-Link:

https://github.com/shikhar/sshj


Es gab ein GSOC-Projekt:

http://code.google.com/p/commons-net-ssh/

Die Codequalität scheint besser zu sein als bei JSch, wo es einer vollständigen und funktionierenden Implementierung an Dokumentation mangelt. Die Projektseite enthält eine bevorstehende Betaversion. Die letzte Übergabe an das Repository erfolgte Mitte August.

Vergleichen Sie die APIs:

http://code.google.com/p/commons-net-ssh/

    SSHClient ssh = new SSHClient();
    //ssh.useCompression(); 
    ssh.loadKnownHosts();
    ssh.connect("localhost");
    try {
        ssh.authPublickey(System.getProperty("user.name"));
        new SCPDownloadClient(ssh).copy("ten", "/tmp");
    } finally {
        ssh.disconnect();
    }

http://www.jcraft.com/jsch/

Session session = null;
Channel channel = null;

try {

JSch jsch = new JSch();
session = jsch.getSession(username, Host, 22);
Java.util.Properties config = new Java.util.Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
session.setPassword(password);
session.connect();

// exec 'scp -f rfile' remotely
String command = "scp -f " + remoteFilename;
channel = session.openChannel("exec");
((ChannelExec) channel).setCommand(command);

// get I/O streams for remote scp
OutputStream out = channel.getOutputStream();
InputStream in = channel.getInputStream();

channel.connect();

byte[] buf = new byte[1024];

// send '\0'
buf[0] = 0;
out.write(buf, 0, 1);
out.flush();

while (true) {
    int c = checkAck(in);
    if (c != 'C') {
        break;
    }

    // read '0644 '
    in.read(buf, 0, 5);

    long filesize = 0L;
    while (true) {
        if (in.read(buf, 0, 1) < 0) {
            // error
            break;
        }
        if (buf[0] == ' ') {
            break;
        }
        filesize = filesize * 10L + (long) (buf[0] - '0');
    }

    String file = null;
    for (int i = 0;; i++) {
        in.read(buf, i, 1);
        if (buf[i] == (byte) 0x0a) {
            file = new String(buf, 0, i);
            break;
        }
    }

    // send '\0'
    buf[0] = 0;
    out.write(buf, 0, 1);
    out.flush();

    // read a content of lfile
    FileOutputStream fos = null;

    fos = new FileOutputStream(localFilename);
    int foo;
    while (true) {
        if (buf.length < filesize) {
            foo = buf.length;
        } else {
            foo = (int) filesize;
        }
        foo = in.read(buf, 0, foo);
        if (foo < 0) {
            // error
            break;
        }
        fos.write(buf, 0, foo);
        filesize -= foo;
        if (filesize == 0L) {
            break;
        }
    }
    fos.close();
    fos = null;

    if (checkAck(in) != 0) {
        System.exit(0);
    }

    // send '\0'
    buf[0] = 0;
    out.write(buf, 0, 1);
    out.flush();

    channel.disconnect();
    session.disconnect();
}

} catch (JSchException jsche) {
    System.err.println(jsche.getLocalizedMessage());
} catch (IOException ioe) {
    System.err.println(ioe.getLocalizedMessage());
} finally {
    channel.disconnect();
    session.disconnect();
}

}
59
miku

Ich habe gerade sshj entdeckt, das eine viel präzisere API zu haben scheint als JSCH (aber es erfordert Java 6). Die Dokumentation ist größtenteils durch Beispiele in der -repo an diesem Punkt, und normalerweise reicht das für mich, um woanders hinzuschauen, aber es scheint gut genug zu sein, um es bei einem Projekt zu versuchen, das ich gerade angefangen habe.

23
Ed Brannin

Schauen Sie sich das kürzlich veröffentlichte SSHD an, das auf dem Apache MINA-Projekt basiert.

18
mshafrir

Es gibt eine brandneue Version von Jsch auf Github: https://github.com/vngx/vngx-jsch Einige der Verbesserungen umfassen: umfassendes Javadoc, verbesserte Leistung, verbesserte Ausnahmebehandlung und bessere Einhaltung der RFC-Spezifikation. Wenn Sie in irgendeiner Weise einen Beitrag leisten möchten, eröffnen Sie bitte ein Problem oder senden Sie eine Pull-Anfrage.

5
Scott

http://code.google.com/p/connectbot/ , kompiliere src\com\trilead\ssh2 unter Windows Linux oder Android, kann lokalen Port erstellen Weiterleitung oder erstellen Sie eine dynamische Port-Weiterleitung oder eine andere

0
a1241312

Ich nahm Mikus Antwort und jsch Beispielcode. Ich musste dann mehrere Dateien herunterladen während der Sitzung und rsprüngliche Zeitstempel beibehalten. Dies ist mein Beispielcode, wahrscheinlich finden es viele Leute nützlich. Bitte ignorieren Sie die filenameHack () Funktion.

package examples;

import com.jcraft.jsch.*;
import Java.io.*;
import Java.util.*;

public class ScpFrom2 {

    public static void main(String[] args) throws Exception {
        Map<String,String> params = parseParams(args);
        if (params.isEmpty()) {
            System.err.println("usage: Java ScpFrom2 "
                    + " user=myid password=mypwd"
                    + " Host=myhost.com port=22"
                    + " encoding=<ISO-8859-1,UTF-8,...>"
                    + " \"remotefile1=/some/file.png\""
                    + " \"localfile1=file.png\""
                    + " \"remotefile2=/other/file.txt\""
                    + " \"localfile2=file.txt\""

            );
            return;
        }

        // default values
        if (params.get("port") == null)
            params.put("port", "22");
        if (params.get("encoding") == null)
            params.put("encoding", "ISO-8859-1"); //"UTF-8"

        Session session = null;
        try {
            JSch jsch=new JSch();
            session=jsch.getSession(
                    params.get("user"),  // myuserid
                    params.get("Host"),  // my.server.com
                    Integer.parseInt(params.get("port")) // 22
            );
            session.setPassword( params.get("password") );
            session.setConfig("StrictHostKeyChecking", "no"); // do not Prompt for server signature

            session.connect();

            // this is exec command and string reply encoding
            String encoding = params.get("encoding");

            int fileIdx=0;
            while(true) {
                fileIdx++;

                String remoteFile = params.get("remotefile"+fileIdx);
                String localFile = params.get("localfile"+fileIdx);
                if (remoteFile == null || remoteFile.equals("")
                        || localFile == null || localFile.equals("") )
                    break;

                remoteFile = filenameHack(remoteFile);
                localFile  = filenameHack(localFile);

                try {
                    downloadFile(session, remoteFile, localFile, encoding);
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }

        } catch(Exception ex) {
            ex.printStackTrace();
        } finally {
            try{ session.disconnect(); } catch(Exception ex){}
        }
    }

    private static void downloadFile(Session session, 
            String remoteFile, String localFile, String encoding) throws Exception {
        // send exec command: scp -p -f "/some/file.png"
        // -p = read file timestamps
        // -f = From remote to local
        String command = String.format("scp -p -f \"%s\"", remoteFile); 
        System.console().printf("send command: %s%n", command);
        Channel channel=session.openChannel("exec");
        ((ChannelExec)channel).setCommand(command.getBytes(encoding));

        // get I/O streams for remote scp
        byte[] buf=new byte[32*1024];
        OutputStream out=channel.getOutputStream();
        InputStream in=channel.getInputStream();

        channel.connect();

        buf[0]=0; out.write(buf, 0, 1); out.flush(); // send '\0'

        // reply: T<mtime> 0 <atime> 0\n
        // times are in seconds, since 1970-01-01 00:00:00 UTC 
        int c=checkAck(in);
        if(c!='T')
            throw new IOException("Invalid timestamp reply from server");

        long tsModified = -1; // millis
        for(int idx=0; ; idx++){
            in.read(buf, idx, 1);
            if(tsModified < 0 && buf[idx]==' ') {
                tsModified = Long.parseLong(new String(buf, 0, idx))*1000;
            } else if(buf[idx]=='\n') {
                break;
            }
        }

        buf[0]=0; out.write(buf, 0, 1); out.flush(); // send '\0'

        // reply: C0644 <binary length> <filename>\n
        // length is given as a text "621873" bytes
        c=checkAck(in);
        if(c!='C')
            throw new IOException("Invalid filename reply from server");

        in.read(buf, 0, 5); // read '0644 ' bytes

        long filesize=-1;
        for(int idx=0; ; idx++){
            in.read(buf, idx, 1);
            if(buf[idx]==' ') {
                filesize = Long.parseLong(new String(buf, 0, idx));
                break;
            }
        }

        // read remote filename
        String origFilename=null;
        for(int idx=0; ; idx++){
            in.read(buf, idx, 1);
            if(buf[idx]=='\n') {
                origFilename=new String(buf, 0, idx, encoding); // UTF-8, ISO-8859-1
                break;
            }
        }

        System.console().printf("size=%d, modified=%d, filename=%s%n"
                , filesize, tsModified, origFilename);

        buf[0]=0; out.write(buf, 0, 1); out.flush(); // send '\0'

        // read binary data, write to local file
        FileOutputStream fos = null;
        try {
            File file = new File(localFile);
            fos = new FileOutputStream(file);
            while(filesize > 0) {
                int read = Math.min(buf.length, (int)filesize);
                read=in.read(buf, 0, read);
                if(read < 0)
                    throw new IOException("Reading data failed");

                fos.write(buf, 0, read);
                filesize -= read;
            }
            fos.close(); // we must close file before updating timestamp
            fos = null;
            if (tsModified > 0)
                file.setLastModified(tsModified);               
        } finally {
            try{ if (fos!=null) fos.close(); } catch(Exception ex){}
        }

        if(checkAck(in) != 0)
            return;

        buf[0]=0; out.write(buf, 0, 1); out.flush(); // send '\0'
        System.out.println("Binary data read");     
    }

    private static int checkAck(InputStream in) throws IOException {
        // b may be 0 for success
        //          1 for error,
        //          2 for fatal error,
        //          -1
        int b=in.read();
        if(b==0) return b;
        else if(b==-1) return b;
        if(b==1 || b==2) {
            StringBuilder sb=new StringBuilder();
            int c;
            do {
                c=in.read();
                sb.append((char)c);
            } while(c!='\n');
            throw new IOException(sb.toString());
        }
        return b;
    }


    /**
     * Parse key=value pairs to hashmap.
     * @param args
     * @return
     */
    private static Map<String,String> parseParams(String[] args) throws Exception {
        Map<String,String> params = new HashMap<String,String>();
        for(String keyval : args) {
            int idx = keyval.indexOf('=');
            params.put(
                    keyval.substring(0, idx),
                    keyval.substring(idx+1)
            );
        }
        return params;
    }

    private static String filenameHack(String filename) {
        // It's difficult reliably pass unicode input parameters 
        // from Java dos command line.
        // This dirty hack is my very own test use case. 
        if (filename.contains("${filename1}"))
            filename = filename.replace("${filename1}", "Korilla ABC ÅÄÖ.txt");
        else if (filename.contains("${filename2}"))
            filename = filename.replace("${filename2}", "test2 ABC ÅÄÖ.txt");           
        return filename;
    }

}
0
Whome