跳到主要內容

SFTP/SSH in JAVA

It is relatively hard to find code examples in Internet regarding SFTP and SSH in java.

Here I have written an example to demonstrate its usage.

Key points

  • I make use of J2SSH v0.2.2
  • The demonstration program is capable of
    • acting as a ssh mini shell
    • run a batch of simple sftp commands stored in a specified file
    • run a batch of simple ssh command stored in a specified file (not yet finished)

Remark:

  • Please note that the crew who made J2SSH has already totally rewritten all of its functions and make it available at commercial market
  • Please do test the speed of the prototype before you decide on whether to use this package. We have tested that it is generally at least 10% slower than sftp version in Unix.

Usage

Application :Sftp/SSH client
Author :Edmund Ng
last update :2009-11-05
version :v0.9a
help :
Example:
This list examples of usage


1.java -jar sftp.jar --help
This starts a ssh mini client
2.java -jar sftp.jar
This makes sftp execute a list of ssh commands stored in batch.txt
3.java -jar sftp.jar -s batch.txt
This makes sftp execute a list of sftp commands stored in batch.txt
4.java -jar sftp.jar -f batch.txt
The username,password and host are stored in config.ini

Code snippet

Mini Shell Code Segment

public static void miniShell()
{
try {
// JDK > 1.4 ONLY
/*Handler fh = new FileHandler("example.log");
fh.setFormatter(new SimpleFormatter());
Logger.getLogger("com.sshtools").setUseParentHandlers(false);
Logger.getLogger("com.sshtools").addHandler(fh);
Logger.getLogger("com.sshtools").setLevel(Level.ALL);*/
// Configure J2SSH (This will attempt to install the bouncycastle provider
// under jdk 1.3.1)

ConfigurationLoader.initialize(false);
BufferedReader reader =
new BufferedReader(new InputStreamReader(System.in));
System.out.print("Connect to host? ");
String hostname = reader.readLine();
// Make a client connection
SshClient ssh = new SshClient();
ssh.setSocketTimeout(30000);
SshConnectionProperties properties = new SshConnectionProperties();
properties.setHost(hostname);
properties.setPrefPublicKey("ssh-dss");
// Connect to the host
ssh.connect(properties);
// Create a password authentication instance
PasswordAuthenticationClient pwd = new PasswordAuthenticationClient();
// Get the users name
System.out.print("Username? ");
// Read the password
String username = reader.readLine();
pwd.setUsername(username);
// Get the password
System.out.print("Password? ");
String password = reader.readLine();
pwd.setPassword(password);
// Try the authentication
int result = ssh.authenticate(pwd);
// Evaluate the result
if (result == AuthenticationProtocolState.COMPLETE) {
System.out.println("Successful login");
// The connection is authenticated we can now do some real work!
SessionChannelClient session = ssh.openSessionChannel();
if(!session.requestPseudoTerminal("ANSI", 80, 24, 0, 0, ""))
System.out.println("Failed to allocate a pseudo terminal");
if (session.startShell()) {
System.out.println("Shell started");
IOStreamConnector input =
new IOStreamConnector();
IOStreamConnector output =
new IOStreamConnector();
IOStreamConnector error =
new IOStreamConnector();
output.setCloseOutput(false);
input.setCloseInput(false);
error.setCloseOutput(false);
input.connect(System.in, session.getOutputStream());

//FileOutputStream fos1=new FileOutputStream("mylog1.log");
//FileOutputStream fos2=new FileOutputStream("mylog2.log");

output.connect(session.getInputStream(), System.out);
//output.connect(session.getInputStream(), fos1);
error.connect(session.getStderrInputStream(), System.out);
//error.connect(session.getStderrInputStream(), fos2);
session.getState().waitForState(ChannelState.CHANNEL_CLOSED);
}else
System.out.println("Failed to start the users shell");
ssh.disconnect();

} else
{
System.out.println("Authentication fail");
} //end if
}
catch (Exception e) {
e.printStackTrace();
}

Connect to SFTP

public static SshClient getSSHClient(String _host,String username,String password)
{
try
{
ConfigurationLoader.initialize(false);
String hostname = _host;
SshClient ssh = new SshClient();
ssh.connect(hostname,new AlwaysAllowingConsoleKnownHostsKeyVerification());
PasswordAuthenticationClient pwd = new PasswordAuthenticationClient();
pwd.setUsername(username);
pwd.setPassword(password);
// Try the authentication
int result = ssh.authenticate(pwd);
// Evaluate the result
if (result == AuthenticationProtocolState.COMPLETE)
{
return ssh;
}else
{
return null;
}
} catch(Exception ex)
{
System.out.println(ex.getMessage());
return null;
}
}//end function

public static void batchSFTP(String filename) throws Exception
{
SshClient ssh=getSSHClient(host,username,password);
if(ssh==null)
{
System.out.println("Authentication fail");
return;
}
SftpClient sftp=ssh.openSftpClient();
if(sftp==null)
{
System.out.println("Connection fail or no such service!");
return;
}
File file=new File(".");
String current_path=file.getCanonicalPath();
sftp.lcd(current_path);
//Read the command list in filename
Vector vLine=HF.readLine(filename);
for(int i=0;i<vLine.size();i++)
{
String command=(String)vLine.get(i);
System.out.println("The command is:"+command);
CommandParser.runCommand(command,sftp);
}//end for
sftp.quit();
ssh.disconnect();
System.out.println("Finished");
//determine the current path
/*
File file=new File(".");
String current_path=file.getCanonicalPath();
sftp.lcd(current_path);
//sftp.put("run.bat");
sftp.put("cron.rar");
sftp.quit();
ssh.disconnect();
System.out.println("Finished");
*/

}//end function

Full class code of AlwaysAllowingConsoleKnownHostsKeyVerification

I think this part is a bit tricky and it takes me sometimes to figure it out in Internet that we can actually override the class to password the interactive login

package net;

import com.sshtools.j2ssh.transport.ConsoleKnownHostsKeyVerification;
import com.sshtools.j2ssh.transport.InvalidHostFileException;
import com.sshtools.j2ssh.transport.publickey.SshPublicKey;

public class AlwaysAllowingConsoleKnownHostsKeyVerification extends
ConsoleKnownHostsKeyVerification {

public AlwaysAllowingConsoleKnownHostsKeyVerification()
throws InvalidHostFileException {
super();
// Don't not do anything else
}

@Override
public void onHostKeyMismatch(String s, SshPublicKey sshpublickey,
SshPublicKey sshpublickey1) {
try
{
System.out.println("The host key supplied by " + s + " is: " + sshpublickey1.getFingerprint());
System.out.println("The current allowed key for " + s + " is: " + sshpublickey.getFingerprint());
System.out.println("~~~Using Custom Key verification, allowing to pass through~~~");
allowHost(s, sshpublickey, false);
}
catch(Exception exception)
{
exception.printStackTrace();
}
}

@Override
public void onUnknownHost(String s, SshPublicKey sshpublickey) {
try
{
System.out.println("The host " + s + " is currently unknown to the system");
System.out.println("The host key fingerprint is: " + sshpublickey.getFingerprint());
System.out.println("~~~Using Custom Key verification, allowing to pass through~~~");
allowHost(s, sshpublickey, false);
}
catch(Exception exception)
{
exception.printStackTrace();
}
}
}

Download:

Full source code with build script can be downloaded at

http://www.iedmund.com/dbwizard/sshsftp.zip

留言

這個網誌中的熱門文章

Setup Tomcat HTTPS (with JDK 8 to Java 15) in 2 mins

  Setup Tomcat 9 HTTPS/SSL To have a quick view, you may see the video(s): https://www.youtube.com/watch?v=WDGoF13vhZU 1. Generate Keystore I am using JDK 15 to generate the keystore. But the steps are similar with Tomcat 6 + openjdk 8(as I have tried it before writing this doc) Use “keytool” command to create a self-signed certificate. During the keystore creation process, you need to assign a password and fill in the certificate’s details. D:\apache-tomcat-9.0.38\conf>keytool -genkey -alias tomcatks -keyalg RSA -keystore D:\apache-tomcat-9.0.38\conf\tomcatks When enter the passwords during generation, please make sure the two passwords you entered are the SAME. This is the requirement of Tomcat. Here is the abstract from Tomcat installation  Finally, you will be prompted for the key password , which is the password specifically for this Certificate (as opposed to any other Certificates stored in the same keystore file). You MUST use the same password here as was used f...

IIS connects to Tomcat. Bug in IIS URL redirect, http2

IIS connects to Web/Application Server Tomcat 9 IIS (Internet Information Server 10) on Windows 2016 server Plesk dropped support for connecting Tomcat from IIS. It is disgraceful. I was so disappointed to learn that. However, another exciting opportunity opened up as I learnt URL rewrite is powerful enough to take over the job and even with more elegant simplicity. So I gave it a try. Even without knowing many of its features, I was able to set it up that one of the sites mysub.yourdomain.com (not real domain, just as an example and I tried a few sites in my server) is pointing to a tomcat localhost at 8080. It sounds good enough. Right?   However, after setting the original site mysub.yourdomain.com for using https. All browsers in desktop platform and Android platform seemed to work. But browser in iOS version failed to open the https. After a few digging, some said in forum that it was a known bug https://stackoverflow.com/questions/49141004/ios-10-3-3-not-working-w...

Find directories with specific size with Java. Recursive Function Demonstration.

The first function draft was generated by AI ChatGPT 3.5. But its comparative function was wrong and AI needed extra guidance to pinpoint that comparison of object in Java needs extra cares. Then its revised its recursive function. However the recursive function provided was still incorrect as it failed to count all the size of files and files inside the subfolders of a specific folder. Then I determined to finish it myself and here is my version. The DirectorySizeChecker is a Java program that allows users to check the sizes of directories in their file system. The program takes in a directory path and an optional minimum size in megabytes as command line arguments, and outputs the paths and sizes of all directories that are equal to or larger than the specified size. The program starts by setting a default minimum size of 100MB if no size argument is provided. It then checks if the correct number of arguments have been provided, and if the input directory exists and is indeed a direc...