SFTP方式通过堡垒机远程上传下载文件到目标主机

首先加入依赖jsch

   <!--  jsch      -->
        <dependency>
            <groupId>com.jcraft</groupId>
            <artifactId>jsch</artifactId>
            <version>0.1.51</version>
        </dependency>

1、创建sftp工具类

import com.jcraft.jsch.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.*;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;


@Slf4j
@Service
public class SftpUtil {

    @Autowired
    private ISSHService sshService;

    @Autowired
    private ISFTPService sftpService;

    @Autowired
    private IHostsService hostsService;

    @Value("${jeecg.path.tmp}")
    private String tmpPath;

    private ChannelSftp channelSftp;

    private Map<String,Session> getSessionMap(String hostId) throws JSchException {
        // 获取远程目标主机
        HostsEntity hostsEntity = hostsService.getById(hostId);
        // 获取ssh配置
        SSHEntity sshEntity = HostUtil.hostEntityToSSHEntity(hostsEntity);
        String hostIp = sshEntity.getHostIp();
        String userName = sshEntity.getUserName();
        String passWord = sshEntity.getPassword();
        int port = sshEntity.getPort();
        int timeOut = sshEntity.getTimeout();
        return sshService.get2Session(hostIp, userName, passWord, port, timeOut);
    }

    private void closeSession(Map<String,Session> sessionMap) {
        Session session = sessionMap.get(SSHConstant.EMOS_SESSION);
        Session sessionServer = sessionMap.get(SSHConstant.EMOS_SERVER_SESSION);
        session.disconnect();
        sessionServer.disconnect();
    }

    /**
     * 根据sftpCfg配置编码获取localPath
     * @param sftpCfgCode sftpCfg配置编码
     */
    public String getLocalPathByCode(String sftpCfgCode){
        SFTPEntity sftpEntity = sftpService.getById(sftpCfgCode);
        return sftpEntity.getLocalPath();
    }

    /**
     * 压缩打包到临时目录(目标主机)并下载到本地临时目录
     * @throws JSchException
     * @throws SftpException
     * @throws IOException
     */
    public String zipFileAndDownload(String hostId,String localPath ,String remotePath,String remoteTmp) throws JSchException, SftpException, IOException {
        Map<String,Session> sshMap = getSessionMap(hostId);
        Session sessionServer = sshMap.get(SSHConstant.EMOS_SERVER_SESSION);
        // 获取通道
        channelSftp = (ChannelSftp) sessionServer.openChannel("sftp");
        // 连接通道
        channelSftp.connect();
        // 返回文件filename
        String filename = null;
        try {
            String fileName = remotePath.substring(remotePath.lastIndexOf("/") + 1);
            //无论是文件夹还是文件打包下载
            //打开通道,设置通道类型,和执行的命令
            Channel channel = sessionServer.openChannel("exec");
            ChannelExec channelExec = (ChannelExec) channel;
            String srcPath = remotePath.substring(0, remotePath.lastIndexOf("/"));
            filename = fileName;
            // 将"/" 的文件夹打包成名为/run/user/download/filename.zip   //+ "_" + UUID.randomUUID().toString()
             String cmdGet = "zip -q -rj  " + remoteTmp + "/" + filename + ".zip " + remotePath;
            channelExec.setCommand("cd " + srcPath + ";" + cmdGet);
            channelExec.setInputStream(null);
            BufferedReader input = new BufferedReader(new InputStreamReader(channelExec.getInputStream()));
            channelExec.connect();
            String line = "";
            while ((line = input.readLine()) != null) {
            }
            System.out.println(remoteTmp + "/" + filename + ".zip");
            channelSftp.get(remoteTmp + "/" + filename + ".zip", localPath);
            // 关闭通道
            channelExec.disconnect();
            input.close();
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw e;
        } finally {
            channelSftp.quit();
            closeSession(sshMap);
        }
        return filename + ".zip";
    }

    /**
     * 下载到本地临时目录
     * @param sftpCfgCode sftpCfg配置编码
     * @param fileName 文件名
     * @throws JSchException
     * @throws SftpException
     */
    public String download(String sftpCfgCode,String fileName) throws JSchException, SftpException {
        // 获取sftp配置
        SFTPEntity sftpEntity = sftpService.getById(sftpCfgCode);
        if (sftpEntity == null){
            throw new EmosException("没有找到对应的sftpCfgCode");
        }
        String remotePath = sftpEntity.getRemotePath();
        String localPath = sftpEntity.getLocalPath();
        // 获取session
        Map<String,Session> sshMap = getSessionMap(sftpEntity.getHostId());
        Session sessionServer = sshMap.get(SSHConstant.EMOS_SERVER_SESSION);
        //通道
        channelSftp = (ChannelSftp) sessionServer.openChannel("sftp");
        //连接通道
     //   channelSftp.quit();
        channelSftp.connect();
        try {
            channelSftp.get(remotePath + fileName, localPath);
            channelSftp.quit();
        } catch (Exception e) {
            throw e;
        } finally {
            channelSftp.quit();
            closeSession(sshMap);
        }
        return localPath;
    }


    /**
     * 文件上传
     * @param sftpCfgCode sftpCfg配置编码
     * @param fileName 文件名
     */
    public void upload(String sftpCfgCode, String fileName) throws Exception {
        // 获取sftp配置
        SFTPEntity sftpEntity = sftpService.getById(sftpCfgCode);
        if (sftpEntity == null){
            throw new EmosException("没有找到对应的sftpCfgCode");
        }
        String remotePath = sftpEntity.getRemotePath();
        String localPath = sftpEntity.getLocalPath();
        // 获取session
        Map<String,Session> sshMap = getSessionMap(sftpEntity.getHostId());
        Session sessionServer = sshMap.get(SSHConstant.EMOS_SERVER_SESSION);
        try {
            //src 文件上传地址
            channelSftp = (ChannelSftp) sessionServer.openChannel("sftp");
            channelSftp.connect();
            channelSftp.put(localPath + fileName, remotePath);
        } catch (Exception e) {
            throw e;
        } finally {
            channelSftp.quit();
            closeSession(sshMap);
        }
    }

    /**
     * 文件上传(资源:需要自定义remotePath的后半段)
     * @param sftpCfgCode sftpCfg配置编码
     * @param fileName 文件名
     */
    public void uploadResource(String sftpCfgCode,InputStream file,String afterRemotePath, String fileName) throws Exception {
        // 获取sftp配置
        SFTPEntity sftpEntity = sftpService.getById(sftpCfgCode);
        if (sftpEntity == null){
            throw new EmosException("没有找到对应的sftpCfgCode");
        }
        String remotePath = sftpEntity.getRemotePath() + "/" + afterRemotePath;
        String localPath = sftpEntity.getLocalPath();
        // 获取session
        Map<String,Session> sshMap = getSessionMap(sftpEntity.getHostId());
        Session sessionServer = sshMap.get(SSHConstant.EMOS_SERVER_SESSION);
        try {
            // 文件上传
            channelSftp = (ChannelSftp) sessionServer.openChannel("sftp");
            channelSftp.connect();
            // 上传目录是否存在
            if (isPathExist(channelSftp,remotePath)){
                //如果存在直接上传
                channelSftp.put(file,remotePath+"/"+fileName);
            } else {
                //如果不存在先创建目录再上传
                mkdirs(channelSftp,remotePath);
                channelSftp.put(file,remotePath + "/"+fileName);
            }
        } catch (Exception e) {
            throw e;
        } finally {
            channelSftp.quit();
            closeSession(sshMap);
        }
    }

    /**
     * 下载资源文件
     * @return 文件绝对路径
     */
    public String downLoadResource(String sftpCfgCode,String afterRemotePath, String fileName) throws Exception {
        // 获取sftp配置
        SFTPEntity sftpEntity = sftpService.getById(sftpCfgCode);
        if (sftpEntity == null){
            throw new EmosException("没有找到对应的sftpCfgCode");
        }
        String localPath = sftpEntity.getLocalPath();
        // 获取session
        Map<String,Session> sshMap = getSessionMap(sftpEntity.getHostId());
        Session sessionServer = sshMap.get(SSHConstant.EMOS_SERVER_SESSION);
        String remotePath = sftpEntity.getRemotePath() + "/" + afterRemotePath;
        try {
            // 文件上传
            channelSftp = (ChannelSftp) sessionServer.openChannel("sftp");
            channelSftp.connect();
            channelSftp.get(remotePath + "/" +fileName, localPath);
            channelSftp.quit();
        } catch (Exception e) {
            throw e;
        } finally {
            channelSftp.quit();
            closeSession(sshMap);
        }
        return localPath + fileName;

    }

    /**
     * 判断路径是否存在
     * @param channelSftp channelSftp
     * @param remotePath remotePath
     */
    private boolean isPathExist(ChannelSftp channelSftp,String remotePath){
        try {
            channelSftp.lstat(remotePath);
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 创建多级目录
     * @param channelSftp channelSftp
     * @param remotePath remotePath
     */
    private void mkdirs(ChannelSftp channelSftp,String remotePath) throws Exception{
        if (remotePath.startsWith("/")){
            remotePath = remotePath.replaceFirst("/","");
        }
        String[] paths = remotePath.split("/");
        for (int i = 0;i<paths.length;i++){
            String path;
            if (i == 0) {
                path = "/" + paths[i];
            } else {
                path = paths[i];
            }
            try {
                channelSftp.cd(path);
            } catch (SftpException e) {
                channelSftp.mkdir(path);
                channelSftp.cd(path);
            }
        }
    }

    public void deleteFile(String sftpCfgCode,String afterRemotePath, String fileName) throws Exception{
        // 获取sftp配置
        SFTPEntity sftpEntity = sftpService.getById(sftpCfgCode);
        if (sftpEntity == null){
            throw new EmosException("没有找到对应的sftpCfgCode");
        }
        // 获取session
        Map<String,Session> sshMap = getSessionMap(sftpEntity.getHostId());
        Session sessionServer = sshMap.get(SSHConstant.EMOS_SERVER_SESSION);
        String remotePath = sftpEntity.getRemotePath() + "/" + afterRemotePath;
        try {
            // 文件上传
            channelSftp = (ChannelSftp) sessionServer.openChannel("sftp");
            channelSftp.connect();
            channelSftp.rm(remotePath + "/" +fileName);
        } catch (Exception e) {
            throw e;
        } finally {
            channelSftp.quit();
            closeSession(sshMap);
        }
    }


    /**
     * 遍历文件名
     *
     * @param hostId hostId
     * @return fileNameList 文件名
     * @throws Exception
     */
    public List<String> listFiles(String hostId,String remotePath) throws Exception {
        // 获取session
        Map<String,Session> sshMap = getSessionMap(hostId);
        Session sessionServer = sshMap.get(SSHConstant.EMOS_SERVER_SESSION);
        try {
            channelSftp = (ChannelSftp) sessionServer.openChannel("sftp");
            //连接通道
            channelSftp.connect();
            Vector fileList;
            List<String> fileNameList = new ArrayList<String>();
            fileList = channelSftp.ls(remotePath);
            Iterator it = fileList.iterator();
            while (it.hasNext()) {
                ChannelSftp.LsEntry entry = (ChannelSftp.LsEntry) it.next();
                String longname = entry.getLongname();
                String fileName = entry.getFilename();
                if (longname.startsWith("d")) {
                    fileName = "d-" + fileName;
                } else if (".".equals(fileName) || "..".equals(fileName) || "d-..".equals(fileName) || "d-.".equals(fileName)) {
                    continue;
                }
                fileNameList.add(fileName);
                channelSftp.quit();
            }
            return fileNameList;
        } catch (Exception e) {
            throw e;
        } finally {
            channelSftp.quit();
            closeSession(sshMap);
        }
    }

    /**
     * 显示文件内容
     *
     * @param hostId hostId
     * @param filenameList 文件名集合
     * @param remotePath 对端路径
     * @return
     * @throws JSchException
     * @throws SftpException
     * @throws InterruptedException
     * @throws IOException
     */
    public Map catFile(String hostId,String remotePath, List<String> filenameList, boolean isCat, String... charSet) throws JSchException, IOException {
        // 获取session
        Map<String,Session> sshMap = getSessionMap(hostId);
        Session sessionServer = sshMap.get(SSHConstant.EMOS_SERVER_SESSION);
        if (charSet[0].toUpperCase().contains("UTF-8")) {
            charSet[0] = "UTF-8";
        } else {
            charSet[0] = "gbk";
        }
        Map scriptMap = new HashMap<>();
        try {
            //String fileName = src.substring(src.lastIndexOf("/") + 1);
            //脚本名为多个时,遍历进行操作
            Iterator<String> filenameIterator = filenameList.iterator();

            while (filenameIterator.hasNext()) {
                StringBuffer sb = new StringBuffer();
                //无论是文件夹还是文件打包下载
                //打开通道,设置通道类型,和执行的命令
                Channel channel = sessionServer.openChannel("exec");
                ChannelExec channelExec = (ChannelExec) channel;

                String filename = String.valueOf(filenameIterator.next());
                String cmdGet = "cat " + filename;
                channelExec.setCommand("cd " + remotePath + ";" + cmdGet);
                channelExec.setInputStream(null);
                BufferedReader input = new BufferedReader(new InputStreamReader(channelExec.getInputStream(), charSet[0]));
                channelExec.connect();
                String line = null;
                if (input != null) {
                    while ((line = input.readLine()) != null) {
                        if (isCat) {
                            sb.append(line + "</br>");
                        } else {
                            sb.append(line + "\n");
                        }
                    }
                } else {
                    sb.append(line);
                }
                // 关闭通道
                input.close();
                channelExec.disconnect();
                //将脚本名与脚本内容封装Map返回
                scriptMap.put(filename, sb);
            }

        } catch (Exception e) {
            throw e;
        } finally {
            closeSession(sshMap);
        }
        return scriptMap;
    }

    public interface PortForwardCallback {
        boolean portForward(int localport) throws Exception;
    }
    private static int randomPort(int minPort, int maxPort) {
        return (int) (Math.floor(Math.random() * (maxPort - minPort + 1)) + minPort);
    }
    public static Session getSession(String hostIp, int port, String username, String password, int milliseconds) throws Exception {
        Session session = null;
        try {
            JSch jsch = new JSch();
            session = jsch.getSession(username, hostIp, port);
            session.setPassword(password);
            if(milliseconds > 0) {
                session.setTimeout(milliseconds);
            }
            Properties config = new Properties();
            config.put("StrictHostKeyChecking", "no");
            config.put("userauth.gssapi-with-mic", "no");
            // 为Session对象设置properties
            session.setConfig(config);
            session.connect();
            log.info("获取Session成功:hostIp:" + hostIp + ";port:" + port + ";username:" + username);
        } catch (Exception e) {
            log.error("获取Session错误:hostIp:" + hostIp + ";port:" + port + ";username:" + username + ";password:" + password);
            throw e;
        }
        return session;
    }
    public static void closeSession(Session session) {
        if(session != null) {
            if(session.isConnected()) {
                session.disconnect();
            }
        }
    }

    /**
     *
     * @param hostIp
     * @param port
     * @param username
     * @param password
     * @param localfileName
     * @param remotePath
     * @throws Exception
     */
    public static void upload(String hostIp, int port, String username, String password, String localfileName, String remotePath) throws Exception {
        Session sessionServer = null;
        ChannelSftp channelSftp = null;
        try {
            sessionServer = getSession(hostIp, port, username, password, 0);
            //src 文件上传地址
            channelSftp = (ChannelSftp) sessionServer.openChannel("sftp");
            channelSftp.connect();
            channelSftp.put(localfileName, remotePath);
            log.info("上传文件成功:hostIp:" + hostIp + ";port:" + port + ";username:" + username + ";password:" + password + ";localfileName:" + localfileName + ";remotePath:" + remotePath);
        } catch (Exception e) {
            log.error("上传文件错误:hostIp:" + hostIp + ";port:" + port + ";username:" + username + ";password:" + password + ";localfileName:" + localfileName + ";remotePath:" + remotePath);
            throw e;
        } finally {
            if(channelSftp != null) channelSftp.quit();
            closeSession(sessionServer);
        }
    }

    public static boolean sshPortForward(String hostIp, int port, String username, String password, int milliseconds,
                                  String forwardHostIp, int forwardPort, PortForwardCallback portForwardCallback) throws Exception {
        Session session = null;
        ChannelExec channelExec = null;
        // 生产主机本地口范围32768 ~ 60999,上生产前需更改;
        int max = 60999;
        int min = 32768;
        long lStartTime = System.currentTimeMillis();
        long lStopTIme;
        Exception portforwardException = null;
        //得到主机信息
        try {
            // 创建堡垒机session并且打开连接,因为创建session之后要主动打开连接
            session = getSession(hostIp, port, username, password, 0);
            int localport = 0;
            List<Integer> listPort = new ArrayList<Integer>();
            for(;;) {
                lStopTIme = System.currentTimeMillis();
                if(milliseconds > 1000 && (lStopTIme - lStartTime) > milliseconds) {
                    localport = 0;
                    break;
                }
                if(listPort.size() > 100) {
                    localport = 0;
                    break;
                }
                int newport = randomPort(min, max);
                if(listPort.contains(newport)) {
                    continue;
                }
                listPort.add(newport);
                try {
                    localport = session.setPortForwardingL(newport, forwardHostIp, forwardPort);
                    break;
                } catch (JSchException e) {
                    portforwardException = e;
                }
            }
            listPort.clear();
            if(localport == 0) {
                if(portforwardException != null) {
                    log.error("建立通道异常" + portforwardException.getMessage(), portforwardException);
                    throw portforwardException;
                }
                log.error("建立通道超时:" + milliseconds + "ms");
                return false;
            }
            log.info("通道建立:HostIp:" + hostIp + ";port:" + port + ";localport:" + localport + "=>forwardHostIp:" + forwardHostIp + ";forwardPort:" + forwardPort);
            //设置命令行超时
            channelExec = (ChannelExec)session.openChannel("exec");
            if(milliseconds > 0) {
                int max_sleep_count = ((milliseconds + 999)/1000 + 9)/10;
                channelExec.setCommand("bash -c 'SLEEP_COUNT=1; while [ $SLEEP_COUNT -le " + max_sleep_count + " ]; do sleep 10; printf \".\"; SLEEP_COUNT=`expr $SLEEP_COUNT + 1`; done'");
            } else {
                channelExec.setCommand("while [ 1 = 1 ];do   sleep 10;   printf \".\"; done");
            }
            return portForwardCallback.portForward(localport);
        } finally {
            if(channelExec != null) {
                if(channelExec.isConnected()) {
                    channelExec.disconnect();
                }
            }
            if(session != null) {
                if(session.isConnected()) {
                    session.disconnect();
                }
            }
        }
    }
    /**
     * 同步文件到对端主机
     *
     * @param filename 文件名
     * @param content 文件内容
     * @return
     * @throws JSchException
     * @throws SftpException
     * @throws InterruptedException
     * @throws IOException
     */

    public void synchronizedFile(String hostId, String remotePath, String filename, String content) throws Exception {
        // 获取session
        Map<String,Session> sshMap = getSessionMap(hostId);
        Session sessionServer = sshMap.get(SSHConstant.EMOS_SERVER_SESSION);
        try {
            DateFormat dateFormat = new SimpleDateFormat("yyyy_MM_dd_HH:mm:ss");
            File dir = new File(tmpPath);
            // 一、检查放置文件的文件夹路径是否存在,不存在则创建
            if (!dir.exists()) {
                dir.mkdirs();// mkdirs创建多级目录
            }
            String nameId = UUID.randomUUID().toString();
            String fileName = filename + "_" + nameId;
            File checkFile = new File(tmpPath + "/" + fileName);
            FileWriter writer = null;
            try {
                // 二、检查目标文件是否存在,不存在则创建
                if (!checkFile.exists()) {
                    checkFile.createNewFile();// 创建目标文件
                }
                // 三、向目标文件中写入内容
                // FileWriter(File file, boolean append),append为true时为追加模式,false或缺省则为覆盖模式
                writer = new FileWriter(checkFile, true);
                writer.append(content);
                writer.flush();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (null != writer)
                    writer.close();
            }
            boolean flag = true;
            if (flag) {
                //src 文件上传地址
                channelSftp = (ChannelSftp) sessionServer.openChannel("sftp");
                channelSftp.connect();
                channelSftp.put(tmpPath + "/" +fileName, remotePath);
                channelSftp.quit();
                flag = false;
            }
            //打开通道,设置通道类型,和执行的命令,判断主机是否存在该文件,文件需要备份
            Channel channelc = sessionServer.openChannel("exec");
            ChannelExec channelExecc = (ChannelExec) channelc;
            //查看改路径下是否有该文件
            channelExecc.setCommand("ls " + remotePath + "/" + filename + "|wc " + "-l");
            channelExecc.setInputStream(null);
            BufferedReader input = new BufferedReader(new InputStreamReader(channelExecc.getInputStream()));
            channelExecc.connect();
            String buf = null;
            StringBuffer sb = new StringBuffer();
            while ((buf = input.readLine()) != null) {
                sb.append(buf);
            }
            // 关闭通道
            channelExecc.disconnect();
            //标记
            boolean copyFlag;
            if (sb.toString().contains("0")) {
                copyFlag = false;
            } else {
                copyFlag = true;
            }
            if (flag == false) {
                //打开通道,设置通道类型,和执行的命令
                Channel channel = sessionServer.openChannel("exec");
                ChannelExec channelExec = (ChannelExec) channel;
                //备份地址 如  mv /app/emos/file/test/c  /app/emos/file/test/test/a1.sh
                String copyScriptSrc = "copy_bac";//备份文件夹名为copy_bac
                String scriptDate = dateFormat.format(new Date());

                //   String cmdGet = "echo " + content + ">" + filename;
                //重命名
                String cmdGet = "mv " + fileName + " " + filename + ";";
                //备份命令
                String copyGet = "mv " + filename + " " + remotePath + "/" + copyScriptSrc + "/" + filename + "_" + scriptDate + ";";

                if (copyFlag) {
                    channelExec.setCommand("cd " + remotePath + ";" + "mkdir " + copyScriptSrc + ";" + copyGet + "cd " + remotePath + ";" + cmdGet);
                    //  channelExec.setCommand("cd " + src + ";" + copyGet + "cd " + src + ";" + cmdGet);
                } else {
                    channelExec.setCommand("cd " + remotePath + ";" + cmdGet);
                }
                //  channelExec.setCommand("cd " + src + ";" + copyGet + "cd " + src + ";" + cmdGet);
                channelExec.connect();
                // 关闭通道
                channelExec.disconnect();
            }
        } catch (Exception e) {
            throw e;
        } finally {
            channelSftp.quit();
            closeSession(sshMap);
        }
    }
}

2、session接口实现类

接口:


import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;

import java.util.Map;

public interface ISSHService {

    // 获取两个session,一个是用于获取channel,另一个是堡垒机的session,使用完需要将两个都关闭
    Map<String,Session> get2Session(String hostIp, String userName, String passWord, int port, int timeout) throws JSchException;

    // 将session缓存到map
    void putCacheSession(String key, Session session);

    // 删除session
    void removeCacheSession(String key);

    // 取出session
    Session getCacheSession(String key);

    // 取出所有session
    Map<String, Session> getAllCacheSession();

    // 取出堡垒机HostId
    public String getHostId();
}

实现类:


import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.MapUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

@Slf4j
@Service("sshService")
public class SSHServiceImpl implements ISSHService {

    // 设置ssh连接的远程端口
    private static final int DEFAULT_SSH_PORT = 22;
    // 配置文件读取堡垒机配置
    @Value("${ScriptExecuteForWard.hostId}")
    private String hostId;

    // 用于存储当前运行的session
    private static Map<String, Session> sessionMap = new HashMap<>();
    @Autowired
    private CfgStaticService cfgStaticService;
    /**
     * 获取两个session,一个是用于获取channel,另一个是堡垒机的session,使用完需要将两个都关闭
     *
     * @param hostIp   hostIp
     * @param userName userName
     * @param passWord passWord
     * @param timeout  timeout
     * @return
     */
    public synchronized Map<String,Session> get2Session(String hostIp, String userName, String passWord, int port, int timeout) throws JSchException {
        // 从数据库中获取堡垒机主机
        Map<String,Object> hostsEntity = cfgStaticService.getCfgStaticById(Integer.parseInt(hostId));
        // 获取ssh配置
        String forWardHostIp ="";
        String forWardUserName="";
        String forWardPassWord="";
        String SSHCfg = MapUtils.getString(hostsEntity,"code_value");
        if (!StringUtils.isEmpty(SSHCfg) && SSHCfg.split("&&").length == 6) {
            forWardHostIp = SSHCfg.split("&&")[0];
            forWardUserName = SSHCfg.split("&&")[2];
            forWardPassWord = SSHCfg.split("&&")[3];
        } else {
            throw new RuntimeException("====未获取到堡垒机信息!====");
        }
        Map<String, Session> resultMap = new HashMap<>(16);
        Session session = null;
        Session sessionServer = null;
        // 生产主机本地口范围32768 ~ 60999,上生产前需更改;
        int max = 60999;
        int min = 32768;
        // 设置本地端口
        Integer localPort;
        //得到主机信息
        try {
            // 创建堡垒机session并且打开连接,因为创建session之后要主动打开连接
            JSch jsch = new JSch();
            session = jsch.getSession(forWardUserName, forWardHostIp, DEFAULT_SSH_PORT);
            //CryptoAndDecrypt.decrypt来进行密码解密
            session.setPassword(forWardPassWord);
            session.setTimeout(timeout);
            Properties config = new Properties();
            config.put("StrictHostKeyChecking", "no");
            config.put("userauth.gssapi-with-mic", "no");
            // 为Session对象设置properties
            session.setConfig(config);
            try {
                session.connect();
            } catch (Exception e) {
                log.info("forWardHostIp:" + forWardHostIp);
                log.info("forWardUserName:" + forWardUserName);
                log.info("forWardPassWord:" + forWardPassWord);
                throw new RuntimeException("堡垒机连接异常:" + e.getMessage(), e);
            }
//            Integer localPortFirst = null;
//            try {
//                localPortFirst = randomPort(min, max);
//                session.setPortForwardingL(localPortFirst, hostIp, port);
//                localPort = localPortFirst;
//                log.info("当前SSH发起端口:" + localPortFirst);
//            } catch (Exception e) {
//                log.error("端口冲突", e.getMessage());
//                Integer catchPort;
//                do {
//                    catchPort = randomPort(min, max);
//                    log.info("SSH重新换端口:" + catchPort);
//                } while (null == localPortFirst || !localPortFirst.equals(catchPort));
//                session.setPortForwardingL(catchPort, hostIp, port);
//                localPort = catchPort;
//            }
//            // 完成上述映射之后,即可通过本地端口连接了,127.0.0.1 为生产主机地址
//            sessionServer = jsch.getSession(userName, "127.0.0.1", localPort);
//            Properties remoteCfg = new Properties();
//            remoteCfg.put("StrictHostKeyChecking", "no");
//            remoteCfg.put("userauth.gssapi-with-mic", "no");
//            remoteCfg.put("PreferredAuthentications", "password,keyboard-interactive");
//            sessionServer.setConfig(remoteCfg);
//            //CryptoAndDecrypt.decrypt进行密码解密
//            sessionServer.setPassword(passWord);
//            sessionServer.setTimeout(timeout);
//            sessionServer.connect();
            // 将获取的两个session返回
            resultMap.put(SSHConstant.EMOS_SERVER_SESSION, session);
//            resultMap.put(SSHConstant.EMOS_SERVER_SESSION, sessionServer);
        } catch (Exception e) {
            if (e.getMessage().contains("local port") || e.getMessage().contains("Address already")) {
                log.error("端口冲突" + e.getMessage(), e);
            } else {
                log.error(e.getMessage(), e);
            }
            session.disconnect();
            sessionServer.disconnect();
            throw e;
        }

        return resultMap;
    }

    private int randomPort(int minPort, int maxPort) {
        return (int) (Math.floor(Math.random() * (maxPort - minPort + 1)) + minPort);
    }

    public String getHostId() {
        return hostId;
    }
    /**
     * 将session缓存到map
     *
     * @param key     缓存标识
     * @param session JSCH的session对象
     * @return
     */
    public void putCacheSession(String key, Session session) {
        sessionMap.put(key, session);
    }

    /**
     * 删除session
     *
     * @param key 缓存标识
     * @return
     */
    public void removeCacheSession(String key) {
        sessionMap.remove(key);
    }

    /**
     * 取出session
     *
     * @param key 缓存标识
     * @return
     */
    public Session getCacheSession(String key) {
        return sessionMap.get(key);
    }

    /**
     * 取出所有session
     *
     * @return
     */
    public Map<String, Session> getAllCacheSession() {
        return sessionMap;
    }
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值