【问题标题】:connect to DB using SSH java使用 SSH java 连接到数据库
【发布时间】:2020-07-10 15:38:41
【问题描述】:

我尝试在 Java 中连接到 Oracle DB,但我遇到了错误,我搜索了很多次我没有找到对我有帮助的东西。

当我尝试使用 SQL 开发人员连接时,它成功了。

所以我尝试编写 java 代码来访问它成功连接到 SSH 的数据库,但在到达 conn = DriverManager.getConnection 时遇到错误:

“java.sql.SQLException:Io 异常:Oracle 错误 ORA-12650”

这是我的功能

public static Connection sshTunel() {
        String sshHost = "sshHost";
        String sshuser = "sshUser";
        String SshKeyFilepath =
            "pathOfKey";
        Session session;
        int localPort = 22;
        String remoteHost = "HostIp";
        int remotePort = 1521;
        String usr = "DB user";
        String pwd = "DB pass";
        try {
            java.util.Properties config = new java.util.Properties();
            JSch jsch = new JSch();
            session = jsch.getSession(sshuser, sshHost, 22);
            jsch.addIdentity(SshKeyFilepath, "ssh Pass");
            config.put("StrictHostKeyChecking", "no");
            config.put("Compression", "yes");
            config.put("ConnectionAttempts", "2");
            session.setConfig(config);
            session.connect();

            System.out.println("SSH Connected ...");

            int assinged_port =
                session.setPortForwardingL(localPort, remoteHost, remotePort);

            System.out.println("localhost:" + assinged_port + " -> " +
                               remoteHost + ":" + remotePort);
            System.out.println("Port Forwarded ...");
            try {
                Class.forName("oracle.jdbc.pool.OracleDataSource");

                conn =
DriverManager.getConnection("jdbc:oracle:thin:@remoteHost:1521/SID",
                            "DB User", "DB Pass");
            } catch (SQLException ex) {
                ex.printStackTrace();
                System.out.println("Error in connection");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return conn;
    }

【问题讨论】:

  • 你为什么连接到remoteHost:1521而不是localhost:<assigned_port>?你说 SQL Developer 连接我有点困惑 - 是直接连接还是也通过 SSH?
  • 如果要通过隧道连接数据库,需要使用 localhost 和本地分配的端口连接到 Oracle
  • 亲爱的我试过 DriverManager.getConnection("jdbc:oracle:thin:@localhost:22/SID", "DB User", "DB Pass") DriverManager.getConnection("jdbc:oracle:thin :@localhost:8080/SID", "DB User", "DB Pass") 同样的错误,请问我该如何处理。
  • @AlexPoole 究竟assigned_port 是什么?我应该将本地主机传递给 int assinged_port = session.setPortForwardingL
  • 抱歉,我听不懂。如果您连接到 remoteHost:1521,则不使用 SSH。如果相关,请编辑您的问题以添加 SQL Developer 连接详细信息以及您如何为此设置 SSH。对于您的 Java 代码,我想知道您是否可能需要调用 setPortForwardingL before connect?

标签: java oracle jdbc jsch


【解决方案1】:

SSH 连接到端口 22。隧道的本地端口应该是不同的非保留端口,例如61521.

然后使用 SQL*Net URL 中的本地地址和端口进行连接。

所以只显示相关部分:

    int localPort = 61521;
    String remoteHost = "HostIp";
    int remotePort = 1521;
    ...
    try {
        java.util.Properties config = new java.util.Properties();
        JSch jsch = new JSch();
        session = jsch.getSession(sshuser, sshHost, 22);
        ...
        session.setConfig(config);

        session.connect();

        System.out.println("SSH Connected ...");

        int assinged_port =
            session.setPortForwardingL(localPort, remoteHost, remotePort);

        System.out.println("localhost:" + assinged_port + " -> " +
                           remoteHost + ":" + remotePort);

        try {
            Class.forName("oracle.jdbc.pool.OracleDataSource");

            conn = DriverManager.getConnection(
                       "jdbc:oracle:thin:@localhost:61521/service_name",
                       "DB User", "DB Pass");
        } catch (SQLException ex) {
        ...

在您的 SQL Developer 屏幕截图中,我希望第一个 Host 值是您的远程主机,即您的代码中实际存在的任何“sshHost”;哪个 SSH 在端口 22 上联系。第二个 Host 和 Port 值是数据库侦听器通过 SSH 会话到达的方式,而不是您。 ('localhost' 是远程服务器;it 将其视为本地主机,并到达环回地址 127.0.0.1)。通过单选按钮选择,该 SSH 连接正在分配自己的本地端口并连接到该端口,您实际上不需要知道它具有什么值。

在您的代码中,此调用:

jsch.getSession(sshuser, sshHost, 22);

这相当于 SQL Developer 对话框中的第一个主机和端口。同样,sshHost 是第一个主机框中的值。

然后这个调用:

session.setPortForwardingL(localPort, remoteHost, remotePort);

相当于 SQL Developer 屏幕截图中的第二个主机和端口部分。这里remoteHost是Host值,大概是localhostremotePort 是端口值,即 1521。

这与 SQL Developer 设置的不同之处在于 localPort 值。在自动分配的 SQL Developer 中(因为您选择了“自动分配本地端口”)。在您的代码中,您指定的是您自己,并且该值必须是非保留端口。

因此,只需相关部分,您就可以执行以下操作:

jsch.getSession(sshuser, 'your_remote_host', 22);
session.connect();
session.setPortForwardingL(61521, 'localhost', 1521);
DriverManager.getConnection(
                   "jdbc:oracle:thin:@localhost:61521/service_name"

有两个对localhost 的引用可能有点令人困惑,而且它们的含义似乎略有不同。那是因为它是一个特殊的环回地址,它保留在计算机内(因此是“本地”)。您可以将第一个(在setPortForwaringL 中)视为远程服务器对其自身的内部引用;第二个(在getConnection() 中)作为您PC 对自身的内部引用。

更令人困惑的是,您的屏幕截图显示了两个主机值的 localhost。如果那是你真正拥有的,那么它没有多大意义,你根本不需要 SSH。因此,我想您更改了真实值以将其隐藏以进行发布,并且只是选择了一个令人困惑的假值,而不是使用 sshHosthostIP 或类似的值。

【讨论】:

  • 感谢您的回复,所以您的意思是我应该在 SQL 开发人员中在本地端口转发填写主机名:localhost 和端口,例如 61521?
  • 如果 SQL Developer 工作,那么不要改变它。您可以更改为“使用特定的本地端口”,然后为此输入 61521,只是为了测试它。但是 (a) 没有必要,并且 (b) 如果您使用该端口号,它将与您的 Java 代码冲突 - 所以保留它或将其恢复为“自动分配”或选择不同的数字。我在回答中添加了更多解释,希望对您有所帮助...
  • 非常感谢您对@Alex Poole 的支持,请在我编辑的帖子中找到 img,当我像附件一样填写它并测试连接 SSH 我得到成功测试但是当我创建数据库连接并选择 SSH我在上面创建的我遇到了错误“从读取调用中得到减一”是管理员应该做的事情还是我这边的事情?
  • 当我尝试代码时,我得到了这个错误:com.jcraft.jsch.JSchException: PortForwardingL: local port 127.0.0.1:61521 cannot be bound。
  • 如果您只从 SQL Developer 测试但没有活动连接,您的 Java 代码将无法使用它;但你不希望它。如果您为两者使用相同的端口,请确保它连接。 only 你的 Java 代码正在运行,我不明白为什么它不起作用;但based on this example 我已将connect 恢复到端口设置之前 - 不确定这是否是最新问题。
猜你喜欢
  • 2010-12-30
  • 2018-09-26
  • 1970-01-01
  • 2019-04-05
  • 2016-10-25
  • 2012-10-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多