SpringBoot 配置ssh连接数据库

前言

有时候我们无法直连上数据库,这时就需要通过代理的形式。

方案1

  1. 导入依赖包
<dependency>
    <groupId>com.jcraft</groupId>
    <artifactId>jsch</artifactId>
    <version>0.1.50</version>
</dependency>
  1. 添加ssh配置
ssh.enabled: true
ssh.remote.ip: 192.168.0.1
ssh.remote.port: 22
ssh.remote.username: root
ssh.remote.password: root
ssh.remote.target_host: 192.168.0.2
ssh.remote.target_port: 3306
ssh.local.resource_host: 127.0.0.1
ssh.local.resource_port: 3307
  1. properties配置类
@Configuration
@Data
@PropertySource(value = "classpath:/config/remote-ssh.properties", encoding = "utf-8", ignoreResourceNotFound = true)
@ConditionalOnResource(resources = {"classpath:/config/remote-ssh.properties"})
public class SshProperties {
    @Value("${ssh.enabled}")
    private boolean enabled;
    @Value("${ssh.remote.ip}")
    private String ip;
    @Value("${ssh.remote.port}")
    private int port;
    @Value("${ssh.remote.username}")
    private String username;
    @Value("${ssh.remote.password}")
    private String passowrd;
    @Value("${ssh.remote.target_host}")
    private String targetHost;
    @Value("${ssh.remote.target_port}")
    private int targetPort;
    @Value("${ssh.local.resource_host}")
    private String resourceHost;
    @Value("${ssh.local.resource_port}")
    private int resourcePort;
}

// 或者这样的方式
@Configuration
@Data
@PropertySource(value = "classpath:/config/remote-ssh.properties", encoding = "utf-8", ignoreResourceNotFound = true)
@ConditionalOnResource(resources = {"classpath:/config/remote-ssh.properties"})
@ConfigurationProperties(prefix = "ssh")
public class SshProperties {
    //    @Value("${ssh.enabled:false}")
    private boolean enabled;

    @Bean
    public Remote getRemote() {
        return new Remote();
    }

    @Bean
    public Local getLocal() {
        return new Local();
    }

    @Data
    @Configuration
    @ConfigurationProperties("ssh.remote")
    public class Remote {
        //    @Value("${ssh.remote.ip}")
        private String ip;
        //    @Value("${ssh.remote.port}")
        private int port;
        //    @Value("${ssh.remote.username}")
        private String username;
        //    @Value("${ssh.remote.password}")
        private String passowrd;
        //    @Value("${ssh.remote.target_host}")
        private String targetHost;
        //    @Value("${ssh.remote.target_port}")
        private int targetPort;
    }

    @Data
    @Configuration
    @ConfigurationProperties("ssh.local")
    public class Local {
        //    @Value("${ssh.local.resource_host}")
        private String resourceHost;
        //    @Value("${ssh.local.resource_port}")
        private int resourcePort;
    }
}
  1. 使用jsch加载SshProperties
@Component
@Slf4j
@ConditionalOnBean(SshProperties.class)
public class SshConfig implements ServletContextInitializer {
    private static Session session;

    @Autowired(required = false)
    private SshProperties sshProperties;


    public Session initSession() {
        try {
            //如果配置文件包含ssh.enabled属性,则使用ssh转发
            if (sshProperties.isEnabled()) {
                Session session = new JSch().getSession(sshProperties.getRemote().getUsername(), sshProperties.getRemote().getIp(), sshProperties.getRemote().getPort());
                session.setConfig("StrictHostKeyChecking", "no");
                session.setPassword(sshProperties.getRemote().getPassowrd());
                session.connect();
                //将本地端口的请求转发到目标地址的端口
                session.setPortForwardingL(sshProperties.getLocal().getResourceHost(), sshProperties.getLocal().getResourcePort(), sshProperties.getRemote().getTargetHost(), sshProperties.getRemote().getTargetPort());
                log.info("ssh forward is open.");
                return session;
            } else {
                log.info("ssh forward is closed.");
            }
        } catch (JSchException e) {
            log.error("ssh JSchException failed.", e);
        } catch (Exception e) {
            log.error("ssh settings is failed. skip!", e);
        }
        return null;
    }

    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        session = initSession();
    }

    /**
     * 断开SSH连接
     */
    public void destroy() {
        this.session.disconnect();
    }
}

到这一步就大功告成了。

参考文章