无法使用 jcraft JSch 连接到 SFTP

问题描述 投票:0回答:1

我正在尝试使用 jcraft 版本 0.1.52 通过 ssh 跳转主机代理连接到 SFTP 位置。但是在我的代码中出现“connection is closed by foreign host”异常。我花了足够多的时间查看文档,但无法弄清楚问题是什么

2016-11-18 14:53:14,091 44977 [main] ERROR c.w.v.r.ftp.JschSftpConnect -
    - com.jcraft.jsch.JSchException: connection is closed by foreign host
        at com.jcraft.jsch.Session.connect(Session.java:269)
        at com.jcraft.jsch.Session.connect(Session.java:183)
        at com.x.y.ftp.JschSftpConnect.connect(JschSftpConnect.java:77)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

私钥没有问题,因为我可以通过 unix 命令连接到 sftp 服务器。

 sftp -o UserKnownHostsFile=/dev/null 
  -o StrictHostKeyChecking=no 
  -i /path/to/host/private-key-file 
    -o 'ProxyCommand=ssh 
        -o UserKnownHostsFile=/dev/null 
        -o StrictHostKeyChecking=no 
        -i /path/to/jumphost/private-key-file
        -l jumphostuser jump.host.com nc sftp.host.com 22' 
  1. 这是我正在运行的代码

代码:

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Properties;

import org.apache.commons.lang3.exception.ExceptionUtils;

import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Proxy;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.SocketFactory;

public class JschSftpConnect {


    public static void main(String args[]) {
        String sftpHostKeyFilePath = "/path/to/host/private-key-file";
        String sftpHost="sftp.host.com";
        String sftpUser="user";
        String proxyHostName="jump.host.com";
        String proxyKeyPath ="/path/to/jumphost/private-key-file";
        String proxyUserName="jumphostuser";

        log.debug("Executing JSCH code.....");
        try {

            JSch jsch = new JSch();

            Path path = FileSystems.getDefault().getPath(sftpHostKeyFilePath);
            byte[] filearray = Files.readAllBytes(path);

            jsch.addIdentity("ID", filearray, null, null);
            Session session = jsch.getSession(sftpUser, sftpHost, 22);
            Properties props = new Properties();
            props.put("StrictHostKeyChecking", "no");
            session.setConfig(props);

            String command = "ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -i "
                + localKeyFileDirectoryName + proxyKey + " -l " + proxyUserName + " " + proxyHostName
                + " nc %h %p";

            session.setProxy(new JumpHostProxyCommand(command));
            log.debug("Connecting session .......................");
            session.connect();
            log.debug("Session openend .......................");

            Channel ch = session.openChannel("sftp");
            ch.connect();
            log.debug("SFTP channel connected .......................");
            ChannelSftp channelSftp = (ChannelSftp) ch;
            channelSftp.cd("/");

            log.debug("Working directory is / .......................");

            byte[] buffer = new byte[1024];
            BufferedInputStream bis = new BufferedInputStream(channelSftp.get("/some_file_.psv"));
            File newFile = new File("some_file_.psv");
            OutputStream os = new FileOutputStream(newFile);
            BufferedOutputStream bos = new BufferedOutputStream(os);
            int readCount;
            // System.out.println("Getting: " + theLine);
            while ((readCount = bis.read(buffer)) > 0) {
                // System.out.println("Writing: ");
                bos.write(buffer, 0, readCount);
            }
            log.debug("File should have been written / .......................");

            while (session != null) {
                System.out.println("Killing the session");
                session.disconnect();
                bis.close();
                bos.close();
                System.exit(0);
            }
        } catch (Exception e) {
            log.error(ExceptionUtils.getStackTrace(e));
        }
    }
}



class JumpHostProxyCommand implements Proxy {

    String command;
    Process p = null;
    InputStream in = null;
    OutputStream out = null;

    public JumpHostProxyCommand(String command) {
        this.command = command;
    }

    public void connect(SocketFactory socket_factory, String host, int port, int timeout) throws Exception {


        String cmd = command.replace("%h", host);
        cmd = cmd.replace("%p", new Integer(port).toString());

        p = Runtime.getRuntime().exec(cmd);
        log.debug("Process returned by proxy command {} , {}", command,  p);
        in = p.getInputStream();
        log.debug("Input stream returned by proxy {}", in);
        out = p.getOutputStream();
        log.debug("Output stream returned by proxy {}", out);
    }

    public Socket getSocket() {
        return null;
    }

    public InputStream getInputStream() {
        return in;
    }

    public OutputStream getOutputStream() {
        return out;
    }

    public void close() {
        try {
            if (p != null) {
                p.getErrorStream().close();
                p.getOutputStream().close();
                p.getInputStream().close();
                p.destroy();
                p = null;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

如果有人能提供帮助,我将不胜感激。谢谢!

java ssh sftp jsch
1个回答
0
投票

这是对我来说效果很好的方法。

基本上这是一条通往 你的 sftp 主机。它通过 jumphost 或隧道主机创建到您的 sftp 主机的隧道,并通过 sftpChannel 从这个隧道“localhost”端口(2222)抓取文件。 我已经通过两个 ssh 主机对其进行了测试。它工作正常。

import com.jcraft.jsch.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Properties;

import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;

public class JschSftpConnect {

    public static final Logger log = LoggerFactory.getLogger(JschSftpConnect.class);
    public static final com.jcraft.jsch.Logger sshLogger = new com.jcraft.jsch.Logger() {
        public boolean isEnabled(int level) {
            return true;
        }

        public void log(int level, String message) {
            switch (level) {
                case 0:
                    log.debug(message);
                    break;
                case 1:
                    log.info(message);
                    break;
                case 2:
                    log.warn(message);
                    break;
                case 3:
                    log.error(message);
                    break;
                case 4:
                    log.error(message);
                    break;
                default:
                    break;

            }
        }
    };

    public static void main(final String args[]) {
        final String tunnelHostKey = "keyfile";
        final String tunnelHost = "sshTunnelHost";
        final String tunnelHostUser = "tunnelsshuser";

        final String sftpKey = "sftpKey";
        final String sftpHost = "sftpHost";
        final String sftpUser = "sftpuser";

        if (args.length >= 2) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        Session tunnelSesssion =
                                createSession(tunnelHostKey, tunnelHost, tunnelHostUser,22);

                        tunnelSesssion.setPortForwardingL
                                (2222,sftpHost,22);

                        Session sftpSession =
                                createSession(sftpKey, "localhost", sftpUser,2222);

                        ChannelSftp sftpChannel =
                                getChannel(sftpSession);

                        if (args.length >= 2) {
                            sftpChannel.cd(args[0]);

                            log.debug("Working directory is " + sftpChannel.pwd());
                            getFileFromSftp(sftpChannel, args[1], args.length == 3 ? args[2] : args[1]);
                        }
                    } catch (Exception e) {
                        log.error(e.getMessage(), e);
                    }
                }
            }).start();
        } else {
            log.info("usage: java JschSftpConnect -cp ... <sftp dir> <sftp infile> <optional out file>");
            System.exit(-1);
        }
    }

    private static Session createSession(
            String keyFile, String host, String user,int port
            ) throws IOException, JSchException {
        JSch jsch = new JSch();
        JSch.setLogger(sshLogger);
        Path path = FileSystems.getDefault().getPath(keyFile);
        byte[] filearray = Files.readAllBytes(path);

        jsch.addIdentity("ID", filearray, null, null);
        Session session = jsch.getSession(user, host, port);
        Properties props = new Properties();
        props.put("StrictHostKeyChecking", "no");
        session.setConfig(props);

        session.setTimeout(1000);
        session.connect();
        if (!session.isConnected()) {
            throw new IOException("Session not connected");
        }
        return session;
    }

    private static ChannelSftp getChannel(Session session)throws IOException, JSchException{
        Channel ch = session.openChannel("sftp");
        log.debug("SFTP channel connected .......................");
        ChannelSftp channelSftp = (ChannelSftp) ch;
        channelSftp.connect(1000);
        return channelSftp;
    }

    private static void getFileFromSftp(ChannelSftp channelSftp, String filename, String outFile) throws SftpException, IOException {
        Path p = Paths.get(outFile != null ? outFile : "output");
        try {
            Files.copy(channelSftp.get(filename), p, REPLACE_EXISTING);
            log.debug("File '" + filename + "' is written");
            System.exit(0);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.