JSch 是SSH2的一个纯Java实现。它允许你连接到一个sshd 服务器,使用端口转发,X11转发,文件传输等等。你可以将它的功能集成到你自己的 程序中。同时该项目也提供一个J2ME版本用来在手机上直连SSHD服务器。
JSCH是一个纯粹的用java实现SSH功能的java library. 官方地址为:http://www.jcraft.com/jsch/
GitHub 地址为:https://github.com/vngx/vngx-jsch
mvn 配置如下:
com.jcraft jsch 0.1.46
demo:
package com.jiepu.jsch;
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
/**
* This program will demonstrate the sftp protocol support.
* $ CLASSPATH=.:../build javac Sftp.java
* $ CLASSPATH=.:../build java Sftp
* You will be asked username, host and passwd.
* If everything works fine, you will get a prompt 'sftp>'.
* 'help' command will show available command.
* In current implementation, the destination path for 'get' and 'put'
* commands must be a file, not a directory.
*
*/
import com.jcraft.jsch.*;
import java.awt.*;
import javax.swing.*;
public class Sftp{
//http://www.jcraft.com/jsch/examples/Sftp.java
public static void main(String[] arg){
try{
JSch jsch=new JSch();
String host=null;
if(arg.length>0){
host=arg[0];
}
else{
host=JOptionPane.showInputDialog("Enter username@hostname",
System.getProperty("user.name")+
"@localhost");
}
String user=host.substring(0, host.indexOf('@'));
host=host.substring(host.indexOf('@')+1);
int port=22;
Session session=jsch.getSession(user, host, port);
// username and password will be given via UserInfo interface.
UserInfo ui=new MyUserInfo();
session.setUserInfo(ui);
session.connect();
Channel channel=session.openChannel("sftp");
channel.connect();
ChannelSftp c=(ChannelSftp)channel;
java.io.InputStream in=System.in;
java.io.PrintStream out=System.out;
java.util.Vector cmds=new java.util.Vector();
byte[] buf=new byte[1024];
int i;
String str;
int level=0;
while(true){
out.print("sftp> ");
cmds.removeAllElements();
i=in.read(buf, 0, 1024);
if(i<=0)break;
i--;
if(i>0 && buf[i-1]==0x0d)i--;
//str=new String(buf, 0, i);
//System.out.println("|"+str+"|");
int s=0;
for(int ii=0; ii0){ cmds.addElement(new String(buf, s, ii-s)); }
while(ii'7'){foo=-1; break;}
foo<<=3;
foo|=(k-'0');
}
if(foo==-1)continue;
}
else{
try{foo=Integer.parseInt((String)cmds.elementAt(1));}
catch(Exception e){continue;}
}
try{
if(cmd.equals("chgrp")){ c.chgrp(foo, path); }
else if(cmd.equals("chown")){ c.chown(foo, path); }
else if(cmd.equals("chmod")){ c.chmod(foo, path); }
}
catch(SftpException e){
System.out.println(e.toString());
}
continue;
}
if(cmd.equals("pwd") || cmd.equals("lpwd")){
str=(cmd.equals("pwd")?"Remote":"Local");
str+=" working directory: ";
if(cmd.equals("pwd")) str+=c.pwd();
else str+=c.lpwd();
out.println(str);
continue;
}
if(cmd.equals("ls") || cmd.equals("dir")){
String path=".";
if(cmds.size()==2) path=(String)cmds.elementAt(1);
try{
java.util.Vector vv=c.ls(path);
if(vv!=null){
for(int ii=0; ii2) continue;
String p1 = cmds.size()==1 ? ".": (String)cmds.elementAt(1);
SftpStatVFS stat = c.statVFS(p1);
long size = stat.getSize();
long used = stat.getUsed();
long avail = stat.getAvailForNonRoot();
long root_avail = stat.getAvail();
long capacity = stat.getCapacity();
System.out.println("Size: "+size);
System.out.println("Used: "+used);
System.out.println("Avail: "+avail);
System.out.println("(root): "+root_avail);
System.out.println("%Capacity: "+capacity);
continue;
}
if(cmd.equals("stat") || cmd.equals("lstat")){
if(cmds.size()!=2) continue;
String p1=(String)cmds.elementAt(1);
SftpATTRS attrs=null;
try{
if(cmd.equals("stat")) attrs=c.stat(p1);
else attrs=c.lstat(p1);
}
catch(SftpException e){
System.out.println(e.toString());
}
if(attrs!=null){
out.println(attrs);
}
else{
}
continue;
}
if(cmd.equals("readlink")){
if(cmds.size()!=2) continue;
String p1=(String)cmds.elementAt(1);
String filename=null;
try{
filename=c.readlink(p1);
out.println(filename);
}
catch(SftpException e){
System.out.println(e.toString());
}
continue;
}
if(cmd.equals("realpath")){
if(cmds.size()!=2) continue;
String p1=(String)cmds.elementAt(1);
String filename=null;
try{
filename=c.realpath(p1);
out.println(filename);
}
catch(SftpException e){
System.out.println(e.toString());
}
continue;
}
if(cmd.equals("version")){
out.println("SFTP protocol version "+c.version());
continue;
}
if(cmd.equals("help") || cmd.equals("?")){
out.println(help);
continue;
}
out.println("unimplemented command: "+cmd);
}
session.disconnect();
}
catch(Exception e){
System.out.println(e);
}
System.exit(0);
}
public static class MyUserInfo implements UserInfo, UIKeyboardInteractive{
public String getPassword(){ return passwd; }
public boolean promptYesNo(String str){
Object[] options={ "yes", "no" };
int foo=JOptionPane.showOptionDialog(null,
str,
"Warning",
JOptionPane.DEFAULT_OPTION,
JOptionPane.WARNING_MESSAGE,
null, options, options[0]);
return foo==0;
}
String passwd;
JTextField passwordField=(JTextField)new JPasswordField(20);
public String getPassphrase(){ return null; }
public boolean promptPassphrase(String message){ return true; }
public boolean promptPassword(String message){
Object[] ob={passwordField};
int result=
JOptionPane.showConfirmDialog(null, ob, message,
JOptionPane.OK_CANCEL_OPTION);
if(result==JOptionPane.OK_OPTION){
passwd=passwordField.getText();
return true;
}
else{ return false; }
}
public void showMessage(String message){
JOptionPane.showMessageDialog(null, message);
}
final GridBagConstraints gbc =
new GridBagConstraints(0,0,1,1,1,1,
GridBagConstraints.NORTHWEST,
GridBagConstraints.NONE,
new Insets(0,0,0,0),0,0);
private Container panel;
public String[] promptKeyboardInteractive(String destination,
String name,
String instruction,
String[] prompt,
boolean[] echo){
panel = new JPanel();
panel.setLayout(new GridBagLayout());
gbc.weightx = 1.0;
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.gridx = 0;
panel.add(new JLabel(instruction), gbc);
gbc.gridy++;
gbc.gridwidth = GridBagConstraints.RELATIVE;
JTextField[] texts=new JTextField[prompt.length];
for(int i=0; i=this.count*100/max){ return true; }
percent=this.count*100/max;
monitor.setNote("Completed "+this.count+"("+percent+"%) out of "+max+".");
monitor.setProgress((int)this.count);
return !(monitor.isCanceled());
}
public void end(){
monitor.close();
}
}
private static String help =
" Available commands:\n"+
" * means unimplemented command.\n"+
"cd path Change remote directory to 'path'\n"+
"lcd path Change local directory to 'path'\n"+
"chgrp grp path Change group of file 'path' to 'grp'\n"+
"chmod mode path Change permissions of file 'path' to 'mode'\n"+
"chown own path Change owner of file 'path' to 'own'\n"+
"df [path] Display statistics for current directory or\n"+
" filesystem containing 'path'\n"+
"help Display this help text\n"+
"get remote-path [local-path] Download file\n"+
"get-resume remote-path [local-path] Resume to download file.\n"+
"get-append remote-path [local-path] Append remote file to local file\n"+
"hardlink oldpath newpath Hardlink remote file\n"+
"*lls [ls-options [path]] Display local directory listing\n"+
"ln oldpath newpath Symlink remote file\n"+
"*lmkdir path Create local directory\n"+
"lpwd Print local working directory\n"+
"ls [path] Display remote directory listing\n"+
"*lumask umask Set local umask to 'umask'\n"+
"mkdir path Create remote directory\n"+
"put local-path [remote-path] Upload file\n"+
"put-resume local-path [remote-path] Resume to upload file\n"+
"put-append local-path [remote-path] Append local file to remote file.\n"+
"pwd Display remote working directory\n"+
"stat path Display info about path\n"+
"exit Quit sftp\n"+
"quit Quit sftp\n"+
"rename oldpath newpath Rename remote file\n"+
"rmdir path Remove remote directory\n"+
"rm path Delete remote file\n"+
"symlink oldpath newpath Symlink remote file\n"+
"readlink path Check the target of a symbolic link\n"+
"realpath path Canonicalize the path\n"+
"rekey Key re-exchanging\n"+
"compression level Packet compression will be enabled\n"+
"version Show SFTP version\n"+
"? Synonym for help";
}
package com.jiepu.jsch;
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
/**
* This program will demonstrate the file transfer from remote to local
* $ CLASSPATH=.:../build javac ScpFrom.java
* $ CLASSPATH=.:../build java ScpFrom user@remotehost:file1 file2
* You will be asked passwd.
* If everything works fine, a file 'file1' on 'remotehost' will copied to
* local 'file1'.
*
*/
import com.jcraft.jsch.*;
import java.awt.*;
import javax.swing.*;
import java.io.*;
public class ScpFrom {
//[email protected]:/home/yunshouhu/info.dat info.dat
// [email protected]:/home/yunshouhu/elasticsearch/elasticsearch-1.7.1//NOTICE.txt info.txt
public static void main(String[] arg) {
if (arg.length != 2) {
System.err
.println("usage: java ScpFrom user@remotehost:file1 file2");
System.exit(-1);
}
FileOutputStream fos = null;
try {
String user = arg[0].substring(0, arg[0].indexOf('@'));
arg[0] = arg[0].substring(arg[0].indexOf('@') + 1);
String host = arg[0].substring(0, arg[0].indexOf(':'));
String rfile = arg[0].substring(arg[0].indexOf(':') + 1);
String lfile = arg[1];
String prefix = null;
if (new File(lfile).isDirectory()) {
prefix = lfile + File.separator;
}
JSch jsch = new JSch();
Session session = jsch.getSession(user, host, 22);
// username and password will be given via UserInfo interface.
UserInfo ui = new MyUserInfo();
session.setUserInfo(ui);
session.connect();
// exec 'scp -f rfile' remotely
String command = "scp -f " + rfile;
Channel 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;
}
}
// System.out.println("filesize="+filesize+", file="+file);
// send '\0'
buf[0] = 0;
out.write(buf, 0, 1);
out.flush();
// read a content of lfile
fos = new FileOutputStream(prefix == null ? lfile : prefix
+ file);
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();
}
session.disconnect();
System.exit(0);
} catch (Exception e) {
System.out.println(e);
try {
if (fos != null)
fos.close();
} catch (Exception ee) {
}
}
}
static int checkAck(InputStream in) throws IOException {
int b = in.read();
// b may be 0 for success,
// 1 for error,
// 2 for fatal error,
// -1
if (b == 0)
return b;
if (b == -1)
return b;
if (b == 1 || b == 2) {
StringBuffer sb = new StringBuffer();
int c;
do {
c = in.read();
sb.append((char) c);
} while (c != '\n');
if (b == 1) { // error
System.out.print(sb.toString());
}
if (b == 2) { // fatal error
System.out.print(sb.toString());
}
}
return b;
}
public static class MyUserInfo implements UserInfo, UIKeyboardInteractive {
public String getPassword() {
return passwd;
}
public boolean promptYesNo(String str) {
Object[] options = { "yes", "no" };
int foo = JOptionPane.showOptionDialog(null, str, "Warning",
JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE,
null, options, options[0]);
return foo == 0;
}
String passwd;
JTextField passwordField = (JTextField) new JPasswordField(20);
public String getPassphrase() {
return null;
}
public boolean promptPassphrase(String message) {
return true;
}
public boolean promptPassword(String message) {
Object[] ob = { passwordField };
int result = JOptionPane.showConfirmDialog(null, ob, message,
JOptionPane.OK_CANCEL_OPTION);
if (result == JOptionPane.OK_OPTION) {
passwd = passwordField.getText();
return true;
} else {
return false;
}
}
public void showMessage(String message) {
JOptionPane.showMessageDialog(null, message);
}
final GridBagConstraints gbc = new GridBagConstraints(0, 0, 1, 1, 1, 1,
GridBagConstraints.NORTHWEST, GridBagConstraints.NONE,
new Insets(0, 0, 0, 0), 0, 0);
private Container panel;
public String[] promptKeyboardInteractive(String destination,
String name, String instruction, String[] prompt, boolean[] echo) {
panel = new JPanel();
panel.setLayout(new GridBagLayout());
gbc.weightx = 1.0;
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.gridx = 0;
panel.add(new JLabel(instruction), gbc);
gbc.gridy++;
gbc.gridwidth = GridBagConstraints.RELATIVE;
JTextField[] texts = new JTextField[prompt.length];
for (int i = 0; i < prompt.length; i++) {
gbc.fill = GridBagConstraints.NONE;
gbc.gridx = 0;
gbc.weightx = 1;
panel.add(new JLabel(prompt[i]), gbc);
gbc.gridx = 1;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.weighty = 1;
if (echo[i]) {
texts[i] = new JTextField(20);
} else {
texts[i] = new JPasswordField(20);
}
panel.add(texts[i], gbc);
gbc.gridy++;
}
if (JOptionPane.showConfirmDialog(null, panel, destination + ": "
+ name, JOptionPane.OK_CANCEL_OPTION,
JOptionPane.QUESTION_MESSAGE) == JOptionPane.OK_OPTION) {
String[] response = new String[prompt.length];
for (int i = 0; i < prompt.length; i++) {
response[i] = texts[i].getText();
}
return response;
} else {
return null; // cancel
}
}
}
}
package com.jiepu.jsch;
/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
/**
* This program will demonstrate how to use "aes128-cbc".
*
*/
import com.jcraft.jsch.*;
import java.awt.*;
import javax.swing.*;
//http://www.jcraft.com/jsch/examples/AES.java
public class AES{
public static void main(String[] arg){
try{
JSch jsch=new JSch();
//jsch.setKnownHosts("/home/foo/.ssh/known_hosts");
String host=null;
if(arg.length>0){
host=arg[0];
}
else{
host=JOptionPane.showInputDialog("Enter username@hostname",
System.getProperty("user.name")+
"@localhost");
}
String user=host.substring(0, host.indexOf('@'));
host=host.substring(host.indexOf('@')+1);
Session session=jsch.getSession(user, host, 22);
//session.setPassword("your password");
// username and password will be given via UserInfo interface.
UserInfo ui=new MyUserInfo("yunshouhu");
session.setUserInfo(ui);
session.setConfig("cipher.s2c", "aes128-cbc,3des-cbc,blowfish-cbc");
session.setConfig("cipher.c2s", "aes128-cbc,3des-cbc,blowfish-cbc");
session.setConfig("CheckCiphers", "aes128-cbc");
session.connect();
Channel channel=session.openChannel("shell");
channel.setInputStream(System.in);
channel.setOutputStream(System.out);
channel.connect();
}
catch(Exception e){
System.out.println(e);
}
}
public static class MyUserInfo implements UserInfo, UIKeyboardInteractive{
public MyUserInfo(String passwd) {
super();
this.passwd = passwd;
}
public String getPassword(){ return passwd; }
public boolean promptYesNo(String str){
return true;
}
String passwd;
public String getPassphrase(){ return null; }
public boolean promptPassphrase(String message){ return true; }
public boolean promptPassword(String message){
return true;
}
public void showMessage(String message){
JOptionPane.showMessageDialog(null, message);
}
public String[] promptKeyboardInteractive(String destination,
String name,
String instruction,
String[] prompt,
boolean[] echo){
return prompt;
}
}
}
4.0.0
com.jiepu
jsch
0.0.1-SNAPSHOT
jar
jsch
http://maven.apache.org
UTF-8
junit
junit
3.8.1
test
com.jcraft
jsch
0.1.53
org.apache.maven.plugins
maven-compiler-plugin
1.7