只问耕耘
分类: Java
2010-01-28 14:39:01
If you’ve worked with Linux or Unix you have undoubtedly encountered SSH. SSH, or secure shell, is defined on wikipedia as “a network protocol that allows data to be exchanged securely between two network devices.” SSH is used for many purposes, including:
A replacement for telnet and rlogin for executing shell commands
To execute a single command on a remote server using rsh
To copy files between servers using SCP
Used with SFTP to support secure FTP
Port forwarding or tunneling
Encrypted VPN, such as with OpenSSH
As a secure proxy with the SOCKS protocol
To create a secure file system using SSHFS
As a bit of background, SSH was created in 1995, but had security vulnerabilities that allowed for a “man in the middle” attack, so SSH-2 was released in 1996. In 2006, SSH-2 became a proposed Internet standard.
Encrypting the transmission of data between servers is very important, especially in current times in which almost every computer is connected to a network. And if you’re writing a Java application that needs to connect to a remote server and transfer sensitive data, it would be nice to take advantage of the work that went into integrating SSH with unix/linux operating systems. The Jakarta Commons Net classes provide support for Telnet, FTP, and a host of other protocols, but not for SSH.
Fortunately, there is a library called Ganymed SSH-2 for Java that implements SSH 2 using AES, Blowfish, and 3DES encryption ciphers in a BSD style license, and using it is very straightforward. Download Ganymed and add ganymed-ssh2-build210.jar (or the latest version) to your CLASSPATH and then implement the following steps:
Create a Connection object, passing it the host name or IP address (as a String) of the server you want to connect to
Call the Connection’s connect() method to connect to the server
Call authenticateWithPassword(), passing it your username and password
Open a Session by calling the Connection’s openSession()
Execute a command by calling the Session’s execCommand() method, passing it the command to execute
Consume the response of the command by invoking the sessions’ getStdOut() (or getStdErr() if you want the error stream), optionally using Ganymed’s StreamGobbler to help you
Close the session by calling the Session’s close() method
Close the connection by calling its close() method
Listing 1 shows the source code for a class called SSHAgent that provides the ability to execute commands on a remote computer using SSH.
Listing 1. SSHAgent.java
package com.javasrc.jolt.agent.ssh;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
import ch.ethz.ssh2.Connection;
import ch.ethz.ssh2.Session;
import ch.ethz.ssh2.StreamGobbler;
import com.javasrc.jolt.component.linux.model.FileSystem;
/**
* The SSHAgent allows a Java application to execute commands on a remote server via SSH
*
* @author shaines
*
*/
public class SSHAgent {
/**
* The hostname (or IP address) of the server to connect to
*/
private String hostname;
/**
* The username of the user on that server
*/
private String username;
/**
* The password of the user on that server
*/
private String password;
/**
* A connection to the server
*/
private Connection connection;
/**
* Creates a new SSHAgent
*
* @param hostname
* @param username
* @param password
*/
public SSHAgent( String hostname, String username, String password )
{
this.hostname = hostname;
this.username = username;
this.password = password;
}
/**
* Connects to the server
*
* @return True if the connection succeeded, false otherwise
*/
public boolean connect() throws SSHException
{
try
{
// Connect to the server
connection = new Connection( hostname );
connection.connect();
// Authenticate
boolean result = connection.authenticateWithPassword( username, password );
System.out.println( "Connection result: " + result );
return result;
}
catch( Exception e )
{
throw new SSHException( "An exception occurred while trying to connect to the host: " + hostname + ", Exception=" + e.getMessage(), e );
}
}
/**
* Executes the specified command and returns the response from the server
*
* @param command The command to execute
* @return The response that is returned from the server (or null)
*/
public String executeCommand( String command ) throws SSHException
{
try
{
// Open a session
Session session = connection.openSession();
// Execute the command
session.execCommand( command );
// Read the results
StringBuilder sb = new StringBuilder();
InputStream stdout = new StreamGobbler( session.getStdout() );
BufferedReader br = new BufferedReader(new InputStreamReader(stdout));
String line = br.readLine();
while( line != null )
{
sb.append( line + "\n" );
line = br.readLine();
}
// DEBUG: dump the exit code
System.out.println( "ExitCode: " + session.getExitStatus() );
// Close the session
session.close();
// Return the results to the caller
return sb.toString();
}
catch( Exception e )
{
throw new SSHException( "An exception occurred while executing the following command: " + command + ". Exception = " + e.getMessage(), e );
}
}
/**
* Logs out from the server
* @throws SSHException
*/
public void logout() throws SSHException
{
try
{
connection.close();
}
catch( Exception e )
{
throw new SSHException( "An exception occurred while closing the SSH connection: " + e.getMessage(), e );
}
}
/**
* Returns true if the underlying authentication is complete, otherwise returns false
* @return
*/
public boolean isAuthenticationComplete()
{
return connection.isAuthenticationComplete();
}
public static void main( String[] args )
{
try
{
SSHAgent sshAgent = new SSHAgent( "192.168.2.3", "username", "mypassword" );
if( sshAgent.connect() )
{
String diskInfo = sshAgent.executeCommand( "df -k" );
System.out.println( "Disk info: " + diskInfo );
String processInfo = sshAgent.executeCommand( "top -b -n 1" );
System.out.println( "Process Info: " + processInfo );
// Logout
sshAgent.logout();
}
}
catch( SSHException e )
{
e.printStackTrace();
}
}
}