Недавно клиент из нашего неожиданно переместил некоторые важные файлы, которые мы собираем с ftp на sftp-сервер. Первоначально у меня создалось впечатление, что было бы просто написать или найти утилиту java, которая может обрабатывать sftp, это определенно не доказано. Что также усугубляет эту проблему, так это то, что мы пытаемся подключиться к серверу sftp с платформы Windows (поэтому определение того, где SSH_HOME находится на клиенте, очень запутано).
Я использую библиотеку apache-commons-vfs и сумел получить решение, которое надежно работает для аутентификации имени пользователя и пароля, но пока ничего не может надежно обрабатывать проверку подлинности с открытым/открытым ключом.
Следующий пример работает для аутентификации имени пользователя и пароля, но я хочу настроить его для проверки подлинности с открытым/открытым ключом.
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);
}
}
У меня есть закрытый ключ, хранящийся в известном месте, и мой открытый ключ был распределен на сервере (мы протестировали, что эти ключи работают успешно при подключении с помощью других инструментов)
Я играл с добавлением следующей строки
SftpFileSystemConfigBuilder.getInstance().setIdentities(this.opts, new File[]{new File("c:/Users/bobtbuilder/.ssh/id_dsa.ppk")});
Это успешно загружает закрытый ключ во всю инфраструктуру, но никогда не использует этот ключ для последующей аутентификации.
Любая помощь или направление, наиболее тепло получившие