Connecting to Remote SFTP server With Password Only In Java

 In this article we will connect to SFTP server using only password as the authentication method.

We will use Apache's VFS library to establish the connection.

Following class show how to:

  • Connect to SFTP server
  • Navigate to a desired folder
  • List of files in a folder
First we need to add the Apache VFS dependency to our project. For maven it can be added to the pom.xml file.

<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-vfs2 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-vfs2</artifactId>
<version>2.9.0</version>
</dependency>

Now let's look at the actual code, in SftpWithPassword class below.

/**
* This class uses Apache's VFS project to connect to remote SFTP server using
* username and password based authentication.
* <p>
* Maven Dependency: https://mvnrepository.com/artifact/org.apache.commons/commons-vfs2
* Apache Commons-VFS Project: https://commons.apache.org/proper/commons-vfs/
*/
public class SftpWithPassword {

public static final String SFTP = "sftp";

/**
* Holds instance of remote SFTP folder.
*/
private FileObject fileObject;

/**
* Direct instantiation not allowed. Use {@link #connect(String, Integer, String, String)}
* method to initiate connection.
*
* @param fileObject
*/
private SftpWithPassword(FileObject fileObject) {
this.fileObject = fileObject;
}

/**
* Initiate connection to remote SFTP server
*
* @param host
* @param port
* @param userName
* @param password
* @return
*/
public static SftpWithPassword connect(String host,
Integer port,
String userName,
String password) throws URISyntaxException, FileSystemException {
URI sftpUri = createSftpUri(host, port, userName, password);
return new SftpWithPassword(VFS.getManager().resolveFile(sftpUri.toString()));
}

/**
* Navigate to specific folder in SFTP
*
* @param folderPath
* @return
*/
public SftpWithPassword cd(String folderPath) throws FileSystemException {
if (this.fileObject == null) {
throw new RuntimeException("SFTP connection not initiated.");
}
FileObject newFolder = this.fileObject.resolveFile(folderPath);
if (!newFolder.exists() || !newFolder.isFolder()) {
throw new RuntimeException("Path does not exist or is not a folder.");
}
this.fileObject = newFolder;
return this;
}

/**
* List all file names. Only file names are listed, not the folders.
*
* @return
*/
public List<String> listFiles() throws FileSystemException {
return ofNullable(this.fileObject.findFiles(SELECT_FILES))
.map(Arrays::asList)
.orElseGet(Collections::emptyList)
.stream()
.map(FileObject::getName)
.map(FileName::getBaseName)
.collect(Collectors.toList());
}

/**
* Create SFTP URI
*
* @param host
* @param port
* @param userName
* @param password
* @return
*/
private static URI createSftpUri(String host,
Integer port,
String userName,
String password) throws URISyntaxException {
String userInfo = userName + ":" + password;
return new URI(SFTP, userInfo, host, Objects.requireNonNullElse(port, -1), null, null, null);
}
}

Sample usage of the SftpWithPassword class would be as below

/**
* Sample usage of {@link SftpWithPassword} class
*/
class SftpWithPasswordTest {

/**
* Test that all files in movies folder are listed.
*
* @throws URISyntaxException
* @throws FileSystemException
*/
public void listAllFiles() throws URISyntaxException, FileSystemException {
List<String> files = SftpWithPassword.connect("localhost", 22, "admin", "password")
.cd("movies")
.listFiles();
Assertions.assertEquals(2, files.size());
}

}

0 comments:

Post a Comment