Acabo de anunciar el nuevo curso Learn Spring , centrado en los fundamentos de Spring 5 y Spring Boot 2:
>> VER EL CURSO1. Introducción
SSH, también conocido como Secure Shell o Secure Socket Shell, es un protocolo de red que permite que una computadora se conecte de manera segura a otra computadora a través de una red no segura. En este tutorial, mostraremos cómo establecer una conexión a un servidor SSH remoto con Java usando las bibliotecas JSch y Apache MINA SSHD .
En nuestros ejemplos, primero abriremos la conexión SSH, luego ejecutaremos un comando, leeremos la salida y la escribiremos en la consola y, finalmente, cerraremos la conexión SSH. Mantendremos el código de muestra lo más simple posible.
2. JSch
JSch es la implementación Java de SSH2 que nos permite conectarnos a un servidor SSH y usar el reenvío de puertos, el reenvío X11 y la transferencia de archivos. Además, tiene una licencia de estilo BSD y nos proporciona una manera fácil de establecer una conexión SSH con Java.
Primero, agreguemos la dependencia JSch Maven a nuestro archivo pom.xml :
com.jcraft jsch 0.1.55
2.1. Implementación
Para establecer una conexión SSH usando JSch, necesitamos un nombre de usuario, contraseña, URL de host y puerto SSH . El puerto SSH predeterminado es 22, pero podría suceder que configuraremos el servidor para usar otro puerto para conexiones SSH:
public static void listFolderStructure(String username, String password, String host, int port, String command) throws Exception { Session session = null; ChannelExec channel = null; try { session = new JSch().getSession(username, host, port); session.setPassword(password); session.setConfig("StrictHostKeyChecking", "no"); session.connect(); channel = (ChannelExec) session.openChannel("exec"); channel.setCommand(command); ByteArrayOutputStream responseStream = new ByteArrayOutputStream(); channel.setOutputStream(responseStream); channel.connect(); while (channel.isConnected()) { Thread.sleep(100); } String responseString = new String(responseStream.toByteArray()); System.out.println(responseString); } finally { if (session != null) { session.disconnect(); } if (channel != null) { channel.disconnect(); } } }
Como podemos ver en el código, primero creamos una sesión de cliente y la configuramos para la conexión a nuestro servidor SSH. Luego, creamos un canal de cliente que se usa para comunicarnos con el servidor SSH donde proporcionamos un tipo de canal, en este caso, exec, lo que significa que pasaremos comandos de shell al servidor.
Además, debemos configurar el flujo de salida para nuestro canal donde se escribirá la respuesta del servidor. Después de establecer la conexión usando el método channel.connect () , se pasa el comando y la respuesta recibida se escribe en la consola.
Veamos cómo usar los diferentes parámetros de configuración que ofrece JSch :
- StrictHostKeyChecking : indica si la aplicación comprobará si la clave pública del host se puede encontrar entre los hosts conocidos. Además, los valores de los parámetros disponibles son ask , yes y no , donde ask es el predeterminado. Si establecemos esta propiedad en yes , JSch nunca agregará automáticamente la clave de host al archivo known_hosts y se negará a conectarse a los hosts cuya clave de host haya cambiado. Esto obliga al usuario a agregar manualmente todos los hosts nuevos. Si lo configuramos en no , JSch agregará automáticamente una nueva clave de host a la lista de hosts conocidos
- compresión.s2c : especifica si se debe utilizar la compresión para el flujo de datos desde el servidor a nuestra aplicación cliente. Los valores disponibles son zlib y none, donde el segundo es el predeterminado
- compresión.c2s : especifica si se debe utilizar la compresión para el flujo de datos en la dirección cliente-servidor. Los valores disponibles son zlib y none, donde el segundo es el predeterminado
Es importante cerrar la sesión y el canal SFTP una vez finalizada la comunicación con el servidor para evitar pérdidas de memoria .
3. Apache MINA SSHD
Apache MINA SSHD proporciona soporte SSH para aplicaciones basadas en Java. Esta biblioteca se basa en Apache MINA, una biblioteca de E / S asíncrona escalable y de alto rendimiento.
Agreguemos la dependencia Apache Mina SSHD Maven:
org.apache.sshd sshd-core 2.5.1
3.1. Implementación
Veamos el ejemplo de código para conectarse al servidor SSH usando Apache MINA SSHD:
public static void listFolderStructure(String username, String password, String host, int port, long defaultTimeoutSeconds, String command) throws IOException { SshClient client = SshClient.setUpDefaultClient(); client.start(); try (ClientSession session = client.connect(username, host, port) .verify(defaultTimeoutSeconds, TimeUnit.SECONDS).getSession()) { session.addPasswordIdentity(password); session.auth().verify(defaultTimeoutSeconds, TimeUnit.SECONDS); try (ByteArrayOutputStream responseStream = new ByteArrayOutputStream(); ClientChannel channel = session.createChannel(Channel.CHANNEL_SHELL)) { channel.setOut(responseStream); try { channel.open().verify(defaultTimeoutSeconds, TimeUnit.SECONDS); try (OutputStream pipedIn = channel.getInvertedIn()) { pipedIn.write(command.getBytes()); pipedIn.flush(); } channel.waitFor(EnumSet.of(ClientChannelEvent.CLOSED), TimeUnit.SECONDS.toMillis(defaultTimeoutSeconds)); String responseString = new String(responseStream.toByteArray()); System.out.println(responseString); } finally { channel.close(false); } } } finally { client.stop(); } }
Cuando trabajamos con Apache MINA SSHD, tenemos una secuencia de eventos bastante similar a la de JSch. Primero, establecemos una conexión a un servidor SSH usando la instancia de la clase SshClient . Si lo inicializamos con SshClient.setupDefaultClient (), podremos trabajar con la instancia que tiene una configuración predeterminada adecuada para la mayoría de los casos de uso. Esto incluye cifrados, compresión, MAC, intercambios de claves y firmas.
Después de eso, crearemos ClientChannel y le adjuntaremos ByteArrayOutputStream , de modo que lo usaremos como flujo de respuesta. Como podemos ver, SSHD requiere tiempos de espera definidos para cada operación. También nos permite definir cuánto tiempo esperará la respuesta del servidor después de que se pase el comando utilizando el método Channel.waitFor () .
Es importante notar que SSHD escribirá la salida completa de la consola en el flujo de respuesta. JSch lo hará solo con el resultado de la ejecución del comando.
La documentación completa sobre Apache Mina SSHD está disponible en el repositorio oficial de GitHub del proyecto.
4. Conclusión
Este artículo ilustró cómo establecer una conexión SSH con Java utilizando dos de las bibliotecas de Java disponibles: JSch y Apache Mina SSHD. También mostramos cómo pasar el comando al servidor remoto y obtener el resultado de la ejecución. Además, las muestras de código completas están disponibles en GitHub.
Fondo de Java