【问题标题】:Spring Data JPA with ssh tunnel to a remote MySQL serverSpring Data JPA 与远程 MySQL 服务器的 ssh 隧道
【发布时间】:2016-02-06 10:34:18
【问题描述】:

我将 Spring Data JPA 与 Hibernate 作为持久性提供程序与远程 MySQL5 服务器一起用于定期复制内部数据子集的作业。该作业(即石英调度的 Java 应用程序)每天运行一次,大约需要 . 30 秒完成同步)。出于安全原因,我们不想为来自外部(即 localhost 以外)的直接连接打开远程服务器。

我已经看到使用 Jsch 以编程方式设置 ssh 隧道的示例,但找不到任何有关如何将 Jsch 与 spring 数据集成的资源。我看到的一个问题是我的某些 spring bean(即 org.apache.commons.configuration.DatabaseConfiguration)是在应用程序启动时创建的,并且已经需要访问数据源。

我可以在应用程序之外打开 ssh 隧道,但它会一直打开,但我想避免这种情况,因为我只需要每天打开 30 秒。

编辑:

经过一番研究,我发现了几种获取 ssh 隧道的方法

A) 实现我自己的数据源(我扩展了 org.springframework.jdbc.datasource.DriverManagerDataSource),然后使用 PostContruct 和 Predestroy 来设置/关闭带有 Jsch 的 ssh 隧道

--> 问题:ssh 隧道在应用程序的生命周期内保持打开状态,这不是我想要的

B) 实现我自己的驱动程序(我扩展了 com.mysql.jdbc.Driver)并覆盖“connect”以在连接之前创建 ssh 隧道

--> 问题:我无法关闭 ssh 隧道连接

欢迎提出更多建议

【问题讨论】:

    标签: java hibernate ssh spring-data jsch


    【解决方案1】:

    如果您的 Spring 配置中有 DataSource bean,您可以创建自己的 DataSource 实现,在尝试使用提供的 JDBC URL 建立连接之前打开一个 SSH 隧道。例如,考虑以下使用 HikariDataSource 的配置:

    <bean id="entityManagerFactory"
      class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
      <property name="dataSource">
        <bean class="com.zaxxer.hikari.HikariDataSource" destroy-method="close">...</bean>
      </property>
    </bean>
    

    您可以扩展类HikariDataSource 以提供您自己的实现。下面是一个例子:

    class TunneledHikariDataSource extends HikariDataSource implements InitializingBean {
      private boolean createTunnel = true;
      private int tunnelPort = 3306;
    
      public void afterPropertiesSet() {
        if(createTunnel) {
          // 1. Extract remote host name from the JDBC URL.
          // 2. Extract/infer remote tunnel port (e.g. 3306)
          // from the JDBC URL.
          // 3. Create a tunnel using Jsch and sample code
          // at http://www.jcraft.com/jsch/examples/PortForwardingL.java.html
          ...
        }
      }
    }
    

    然后,为自定义类实例化一个 bean 实例,而不是 HikariDataSource

    【讨论】:

    • 感谢您的提示,不知道我可以提供自己的数据源实现。由于我目前正在使用 jndi 数据源(org.springframework.jnd.JndiObjectFactoryBean),我仍然需要了解如何获取连接 url/端口(我在 Tomcat 的上下文中定义)
    • 也将主机名和端口公开为 bean 上的属性。除了createTunneltunnelPort,你还可以有remoteHostremotePort
    • 以及如何获得关闭连接的句柄(关闭 ssh 隧道?)。据我了解,这是在 Connection 对象本身中实现的(在我的例子中是一个实现 java.sql.Connectio 的类?
    • 为什么要在每次连接请求时打开和关闭隧道?建立隧道是一项昂贵的操作,因此会减慢您的操作速度。如果您真的想在每个连接上打开和关闭隧道,则必须实现自己的 Connection 类,因为您正在使用连接生命周期。另外,请分别提出不同的问题。
    猜你喜欢
    • 2016-08-04
    • 2016-02-13
    • 1970-01-01
    • 2012-10-02
    • 2014-05-03
    • 2014-12-13
    • 2019-12-07
    • 1970-01-01
    • 2016-11-18
    相关资源
    最近更新 更多