Recientemente, un cliente de nuestro equipo cambió inesperadamente algunos archivos importantes que recopilamos de un servidor ftp a sftp. Inicialmente tenía la impresión de que sería simple escribir o encontrar una utilidad java que pueda manejar sftp, definitivamente este no ha sido el caso. Lo que también ha agravado este problema es que estamos tratando de conectarnos al servidor sftp desde una plataforma de Windows (por lo que la definición de dónde se encuentra SSH_HOME en el cliente se confunde mucho).Ejemplo confiable de cómo usar SFTP usando autenticación de clave pública privada con Java
He estado utilizando la biblioteca apache-commons-vfs y he logrado obtener una solución que funciona confiablemente para la autenticación de nombre de usuario/contraseña, pero todavía no hay nada que pueda manejar confiablemente la autenticación de clave privada/pública.
El siguiente ejemplo funciona para la autenticación de nombre de usuario/contraseña, pero quiero ajustarlo para la autenticación de clave privada/pública.
public static void sftpGetFile(String server, String userName,String password,
String remoteDir, String localDir, String fileNameRegex)
{
File localDirFile = new File(localDir);
FileSystemManager fsManager = null;
if (!localDirFile.exists()) {
localDirFile.mkdirs();
}
try {
fsManager = VFS.getManager();
} catch (FileSystemException ex) {
LOGGER.error("Failed to get fsManager from VFS",ex);
throw new RuntimeException("Failed to get fsManager from VFS", ex);
}
UserAuthenticator auth = new StaticUserAuthenticator(null, userName,password);
FileSystemOptions opts = new FileSystemOptions();
try {
DefaultFileSystemConfigBuilder.getInstance().setUserAuthenticator(opts,
auth);
} catch (FileSystemException ex) {
LOGGER.error("setUserAuthenticator failed", ex);
throw new RuntimeException("setUserAuthenticator failed", ex);
}
Pattern filePattern = Pattern.compile(fileNameRegex);
String startPath = "sftp://" + server + remoteDir;
FileObject[] children;
// Set starting path on remote SFTP server.
FileObject sftpFile;
try {
sftpFile = fsManager.resolveFile(startPath, opts);
LOGGER.info("SFTP connection successfully established to " +
startPath);
} catch (FileSystemException ex) {
LOGGER.error("SFTP error parsing path " +
remoteDir,
ex);
throw new RuntimeException("SFTP error parsing path " +
remoteDir,
ex);
}
// Get a directory listing
try {
children = sftpFile.getChildren();
} catch (FileSystemException ex) {
throw new RuntimeException("Error collecting directory listing of " +
startPath, ex);
}
search:
for (FileObject f : children) {
try {
String relativePath =
File.separatorChar + f.getName().getBaseName();
if (f.getType() == FileType.FILE) {
System.out.println("Examining remote file " + f.getName());
if (!filePattern.matcher(f.getName().getPath()).matches()) {
LOGGER.info(" Filename does not match, skipping file ." +
relativePath);
continue search;
}
String localUrl = "file://" + localDir + relativePath;
String standardPath = localDir + relativePath;
System.out.println(" Standard local path is " + standardPath);
LocalFile localFile =
(LocalFile) fsManager.resolveFile(localUrl);
System.out.println(" Resolved local file name: " +
localFile.getName());
if (!localFile.getParent().exists()) {
localFile.getParent().createFolder();
}
System.out.println(" ### Retrieving file ###");
localFile.copyFrom(f,
new AllFileSelector());
} else {
System.out.println("Ignoring non-file " + f.getName());
}
} catch (FileSystemException ex) {
throw new RuntimeException("Error getting file type for " +
f.getName(), ex);
}
}
FileSystem fs = null;
if (children.length > 0) {
fs = children[0].getFileSystem(); // This works even if the src is closed.
fsManager.closeFileSystem(fs);
}
}
Tengo mi clave privada almacenada en un lugar conocido y mi clave pública ha sido distrubuted al servidor (que hemos probado que estas teclas funcionan con éxito cuando se conecta utilizando otras herramientas)
tengo jugado un poco con la adición de la siguiente línea
SftpFileSystemConfigBuilder.getInstance().setIdentities(this.opts, new File[]{new File("c:/Users/bobtbuilder/.ssh/id_dsa.ppk")});
Esto carga con éxito la clave privada en todo el marco, pero nunca a continuación, utiliza esa clave para autentificar aún más.
Cualquier ayuda o dirección más calurosa recibida
¿No es 'ppk' una cosa masilla? ¿No deberías estar usando un 'pem'? – prodigitalson
Posiblemente, pero no son servidores/clientes sftp independientes de cómo se crean las claves. Pensé que lo importante era que solo seguían el estándar open-ssh? – grumblebee