Reliable example of how to use SFTP using public private key authentication with Java

前端 未结 3 894
生来不讨喜
生来不讨喜 2021-01-31 05:41

Recently a client of our unexpectedly shifted some important files we collect from an ftp to sftp server. Initially I was under the impression that it would be simple to write

相关标签:
3条回答
  • 2021-01-31 06:00

    This post and answer were very helpful, thank you very much.

    I just want to add an integration to the statement "currently the apache-commons-vfs2 library does not support passphrases", as I did it also with passphrase and it worked.

    You have to import the jsch library in your project (I used 0.1.49) and implement the interface "com.jcraft.jsch.UserInfo".

    Something like this should be fine:

    public class SftpUserInfo implements UserInfo {
    
        public String getPassphrase() {
            return "yourpassphrase";
        }
    
        public String getPassword() {
            return null;
        }
    
        public boolean promptPassphrase(String arg0) {
            return true;
        }
    
        public boolean promptPassword(String arg0) {
            return false;
        }
    }
    

    And then you can add it to the SftpFileSystemConfigBuilder this way:

    SftpFileSystemConfigBuilder.getInstance().setUserInfo(fsOptions, new SftpUserInfo());
    

    Hope this helps.

    0 讨论(0)
  • 2021-01-31 06:12

    I guess this is what you are looking for -

    /**
    * @param args
    */
    public static void main(String[] args) {
    
        /*Below we have declared and defined the SFTP HOST, PORT, USER
                and Local private key from where you will make connection */
        String SFTPHOST = "10.20.30.40";
        int    SFTPPORT = 22;
        String SFTPUSER = "kodehelp";
        // this file can be id_rsa or id_dsa based on which algorithm is used to create the key
        String privateKey = "/home/kodehelp/.ssh/id_rsa";
        String SFTPWORKINGDIR = "/home/kodehelp/";
    
        JSch jSch = new JSch();
        Session     session     = null;
        Channel     channel     = null;
        ChannelSftp channelSftp = null;
        try {
            jSch.addIdentity(privateKey);
            System.out.println("Private Key Added.");
            session = jSch.getSession(SFTPUSER,SFTPHOST,SFTPPORT);
            System.out.println("session created.");
    
            java.util.Properties config = new java.util.Properties();
            config.put("StrictHostKeyChecking", "no");
            session.setConfig(config);
            session.connect();
            channel = session.openChannel("sftp");
            channel.connect();
            System.out.println("shell channel connected....");
            channelSftp = (ChannelSftp)channel;
            channelSftp.cd(SFTPWORKINGDIR);
            System.out.println("Changed the directory...");
        } catch (JSchException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (SftpException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }finally{
            if(channelSftp!=null){
                channelSftp.disconnect();
                channelSftp.exit();
            }
            if(channel!=null) channel.disconnect();
    
            if(session!=null) session.disconnect();
        }
    }
    

    See more at

    http://kodehelp.com/sftp-connection-public-key-authentication-java/

    0 讨论(0)
  • 2021-01-31 06:21

    After much digging around I finally got to the answer myself. Seems that much of my bother was to do with the format of the private and public key

    privateKey must be in openSSH format publicKey for whatever reason can only be pasted from the puttyGen window (exporting the public key always seemed to give it with missing headers meaning the freeSSHD windows server could not use it)

    Anyhow below is my code I finally came up with including the javadoc, so hopefully should save some others the pain I went through

    /**
    * Fetches a file from a remote sftp server and copies it to a local file location.  The authentication method used
    * is public/private key authentication. <br><br>
    
    * IMPORTANT: Your private key must be in the OpenSSH format, also it must not have a passphrase associated with it.
    *    (currently the apache-commons-vfs2 library does not support passphrases)<p>
    * 
    * Also remember your public key needs to be on the sftp server.  If you were connecting as user 'bob' then your
    * public key will need to be in '.ssh/bob' on the server (the location of .ssh will change depending on the type
    * of sftp server)
    * 
    * @param server The server we care connection to 
    * @param userName The username we are connection as
    * @param openSSHPrivateKey The location of the  private key (which must be in openSSH format) on the local machine
    * @param remoteDir The directory from where you want to retrieve the file on the remote machine (this is in reference to SSH_HOME, SSH_HOME is the direcory you 
    * automatically get directed to when connecting)
    * @param remoteFile The name of the file on the remote machine to be collected (does not support wild cards)
    * @param localDir The direcoty on the local machine where you want the file to be copied to
    * @param localFileName The name you wish to give to retrieved file on the local machine
    * @throws IOException - Gets thrown is there is any problem fetching the file
    */
    public static void sftpGetFile_keyAuthentication(String server, String userName, String openSSHPrivateKey,
        String remoteDir,String remoteFile, String localDir, String localFileName) throws IOException
    {
    
       FileSystemOptions fsOptions = new FileSystemOptions();
       FileSystemManager fsManager = null;
       String remoteURL = "sftp://" + userName + "@" + server + "/" + remoteDir + "/" + remoteFile;
       String localURL  = "file://" + localDir + "/" + localFileName;
    
        try {
            SftpFileSystemConfigBuilder.getInstance().setStrictHostKeyChecking(fsOptions, "no");
            SftpFileSystemConfigBuilder.getInstance().setIdentities(fsOptions, new File[]{new File(openSSHPrivateKey)});
            fsManager = VFS.getManager();
            FileObject remoteFileObject = fsManager.resolveFile(remoteURL, fsOptions);
            LocalFile localFile =
                       (LocalFile) fsManager.resolveFile(localURL);
            localFile.copyFrom(remoteFileObject,
                       new AllFileSelector());
        } catch (FileSystemException e) {
            LOGGER.error("Problem retrieving from " + remoteURL + " to " + localURL,e );
            throw new IOException(e);
        }
    }
    
    0 讨论(0)
提交回复
热议问题