I'm trying to connect to a sftp server, which I connect to via commands using sftp -oHostKeyAlgorithms=+ssh-dss user@host
. However, when I try to connect via my java-spring application, using apache vfs, I get the following exception:
ERROR] 20/06/2023 11:50:13.333 [http-nio-8080-exec-1] o.a.c.c.C.[.[.[.[dispatcherServlet] - Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.RuntimeException: org.apache.commons.vfs2.FileSystemException: Could not connect to SFTP server at "sftp://user:***@host/".] with root cause
com.jcraft.jsch.JSchException: Algorithm negotiation fail
My file download method looks like this:
public void downloadFile(final String originFilePath, final String destinationFilePath) throws IOException {
try (final StandardFileSystemManager manager = new StandardFileSystemManager()) {
manager.init();
final FileObject remoteFile = manager.resolveFile(getConnectionWithPath(originFilePath), createDefaultOptions());
manager.resolveFile(destinationFilePath).copyFrom(remoteFile, Selectors.SELECT_SELF);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
The getConnectionWithPath(originFilePath) looks like this (the getX() methods retrieve the value from my properties file):
public String getConnectionWithPath(final String remoteFilePath) {
return "sftp://" + getUser() + ":" + getPassword() + "@" + getIp() + "/" + remoteFilePath;
}
And finally, my createDefaultOptions() method:
public static FileSystemOptions createDefaultOptions() throws FileSystemException {
FileSystemOptions opts = new FileSystemOptions();
SftpFileSystemConfigBuilder.getInstance().setUserDirIsRoot(opts, false);
SftpFileSystemConfigBuilder.getInstance().setKeyExchangeAlgorithm(opts, "ssh-dss");
SftpFileSystemConfigBuilder.getInstance().setDisableDetectExecChannel(opts, true);
return opts;
}
I'm using jsch 0.1.55 and apache vfs 2.9.0
After trying many approaches, I ended up using just jsch to create the connection and download the files I need, using the following methods:
public void downloadFile(String originFilePath, String destinationFilePath) throws IOException {
try {
final Session session = createSessionAndConnect();
ChannelSftp sftpChannel = getJSCHConnectionChannel(session);
sftpChannel.get(originFilePath, destinationFilePath);
closeJSCHConnectionChannel(sftpChannel, session);
} catch (JSchException | SftpException e) {
e.printStackTrace();
}
}
private Session createSessionAndConnect() throws JSchException {
JSch jsch = new JSch();
Session session = null;
session = jsch.getSession(getUser(), getIp(), 22);
session.setConfig("StrictHostKeyChecking", "no"); // Is this fine?
session.setPassword(getPassword());
session.connect();
return session;
}
private ChannelSftp getJSCHConnectionChannel(Session session) throws JSchException {
Channel channel = session.openChannel("sftp");
channel.connect();
return (ChannelSftp) channel;
}
private void closeJSCHConnectionChannel(final ChannelSftp sftpChannel, final Session session) {
sftpChannel.exit();
session.disconnect();
}