подключиться к удаленной базе данных mysql через ssh с помощью java

Как подключиться к удаленной базе данных MySQL через SSH из приложения Java. Маленький пример кода полезен для меня, и я был бы признателен за это.

Я понимаю, что вы хотите получить доступ к серверу mysql, работающему на удаленной машине, и прослушать, скажем, порт 3306 через туннель SSH.

Чтобы создать такой туннель из порта 1234 на вашем локальном компьютере на порт 3306 на удаленном компьютере с помощью командной строки ssh client, вы должны ввести следующую команду с вашей локальной машины:

ssh -L 1234:localhost:3306 mysql.server.remote 

Чтобы сделать то же самое с Java, вы можете использовать JSch , Java-реализацию SSH2. На своем веб-сайте:

JSch позволяет подключаться к серверу sshd и использовать переадресацию портов, пересылку X11, передачу файлов и т. Д., И вы можете интегрировать свои функции в свои собственные программы Java. JSch лицензируется по лицензии типа BSD.

Например, посмотрите на PortForwardingL.java . После подключения сеанса создайте соединение JDBC с MySQL, используя в качестве URL-адреса что-то вроде jdbc:mysql://localhost:1234/[database] .

Мой код ниже:

 package mypackage; import java.sql.*; import com.jcraft.jsch.JSch; import com.jcraft.jsch.Session; public class UpdateMySqlDatabase { static int lport; static String rhost; static int rport; public static void go(){ String user = "ripon"; String password = "wasim"; String host = "myhost.ripon.wasim"; int port=22; try { JSch jsch = new JSch(); Session session = jsch.getSession(user, host, port); lport = 4321; rhost = "localhost"; rport = 3306; session.setPassword(password); session.setConfig("StrictHostKeyChecking", "no"); System.out.println("Establishing Connection..."); session.connect(); int assinged_port=session.setPortForwardingL(lport, rhost, rport); System.out.println("localhost:"+assinged_port+" -> "+rhost+":"+rport); } catch(Exception e){System.err.print(e);} } public static void main(String[] args) { try{ go(); } catch(Exception ex){ ex.printStackTrace(); } System.out.println("An example for updating a Row from Mysql Database!"); Connection con = null; String driver = "com.mysql.jdbc.Driver"; String url = "jdbc:mysql://" + rhost +":" + lport + "/"; String db = "testDB"; String dbUser = "wasim"; String dbPasswd = "riponalwasim123"; try{ Class.forName(driver); con = DriverManager.getConnection(url+db, dbUser, dbPasswd); try{ Statement st = con.createStatement(); String sql = "UPDATE MyTableName " + "SET email = '[email protected]' WHERE email='[email protected]'"; int update = st.executeUpdate(sql); if(update >= 1){ System.out.println("Row is updated."); } else{ System.out.println("Row is not updated."); } } catch (SQLException s){ System.out.println("SQL statement is not executed!"); } } catch (Exception e){ e.printStackTrace(); } } } 
 import java.sql.Connection; import java.sql.DriverManager; import java.util.Properties; import com.jcraft.jsch.JSch; import com.jcraft.jsch.JSchException; import com.jcraft.jsch.Session; public class CTestDriver { private static void doSshTunnel(String strSshUser, String strSshPassword, String strSshHost, int nSshPort, String strRemoteHost, int nLocalPort, int nRemotePort) throws JSchException { final JSch jsch = new JSch(); Session session = jsch.getSession(strSshUser, strSshHost, 22); session.setPassword(strSshPassword); final Properties config = new Properties(); config.put("StrictHostKeyChecking", "no"); session.setConfig(config); session.connect(); session.setPortForwardingL(nLocalPort, strRemoteHost, nRemotePort); } public static void main(String[] args) { try { String strSshUser = "ssh_user_name"; // SSH loging username String strSshPassword = "abcd1234"; // SSH login password String strSshHost = "your.ssh.hostname.com"; // hostname or ip or // SSH server int nSshPort = 22; // remote SSH host port number String strRemoteHost = "your.database.hostname.com"; // hostname or // ip of // your // database // server int nLocalPort = 3366; // local port number use to bind SSH tunnel int nRemotePort = 3306; // remote port number of your database String strDbUser = "db_user_name"; // database loging username String strDbPassword = "4321dcba"; // database login password CTestDriver.doSshTunnel(strSshUser, strSshPassword, strSshHost, nSshPort, strRemoteHost, nLocalPort, nRemotePort); Class.forName("com.mysql.jdbc.Driver"); Connection con = DriverManager.getConnection("jdbc:mysql://localhost:" + nLocalPort, strDbUser, strDbPassword); con.close(); } catch (Exception e) { e.printStackTrace(); } finally { System.exit(0); } } } 
 package framework.restapi.utils; import java.sql.*; import com.jcraft.jsch.JSch; import com.jcraft.jsch.Session; import com.mysql.jdbc.jdbc2.optional.MysqlDataSource; import java.sql.Connection; import java.util.ArrayList; import java.util.List; public class SQLConnection { private static Connection connection = null; private static Session session = null; private static void connectToServer(String dataBaseName) throws SQLException { connectSSH(); connectToDataBase(dataBaseName); } private static void connectSSH() throws SQLException { String sshHost = ""; String sshuser = ""; String dbuserName = ""; String dbpassword = ""; String SshKeyFilepath = "/Users/XXXXXX/.ssh/id_rsa"; int localPort = 8740; // any free port can be used String remoteHost = "127.0.0.1"; int remotePort = 3306; String localSSHUrl = "localhost"; /***************/ String driverName = "com.mysql.jdbc.Driver"; try { java.util.Properties config = new java.util.Properties(); JSch jsch = new JSch(); session = jsch.getSession(sshuser, sshHost, 22); jsch.addIdentity(SshKeyFilepath); config.put("StrictHostKeyChecking", "no"); config.put("ConnectionAttempts", "3"); session.setConfig(config); session.connect(); System.out.println("SSH Connected"); Class.forName(driverName).newInstance(); int assinged_port = session.setPortForwardingL(localPort, remoteHost, remotePort); System.out.println("localhost:" + assinged_port + " -> " + remoteHost + ":" + remotePort); System.out.println("Port Forwarded"); } catch (Exception e) { e.printStackTrace(); } } private static void connectToDataBase(String dataBaseName) throws SQLException { String dbuserName = "sf2_showpad_biz"; String dbpassword = "lOAWEnL3K"; int localPort = 8740; // any free port can be used String localSSHUrl = "localhost"; try { //mysql database connectivity MysqlDataSource dataSource = new MysqlDataSource(); dataSource.setServerName(localSSHUrl); dataSource.setPortNumber(localPort); dataSource.setUser(dbuserName); dataSource.setAllowMultiQueries(true); dataSource.setPassword(dbpassword); dataSource.setDatabaseName(dataBaseName); connection = dataSource.getConnection(); System.out.print("Connection to server successful!:" + connection + "\n\n"); } catch (Exception e) { e.printStackTrace(); } } private static void closeConnections() { CloseDataBaseConnection(); CloseSSHConnection(); } private static void CloseDataBaseConnection() { try { if (connection != null && !connection.isClosed()) { System.out.println("Closing Database Connection"); connection.close(); } } catch (SQLException e) { e.printStackTrace(); } } private static void CloseSSHConnection() { if (session != null && session.isConnected()) { System.out.println("Closing SSH Connection"); session.disconnect(); } } // works ONLY FOR single query (one SELECT or one DELETE etc) private static ResultSet executeMyQuery(String query, String dataBaseName) { ResultSet resultSet = null; try { connectToServer(dataBaseName); Statement stmt = connection.createStatement(); resultSet = stmt.executeQuery(query); System.out.println("Database connection success"); } catch (SQLException e) { e.printStackTrace(); } return resultSet; } public static void DeleteOrganisationReferencesFromDB(String organisationsLike) { try { connectToServer("ServerName"); Statement stmt = connection.createStatement(); ResultSet resultSet = stmt.executeQuery("select * from DB1"); String organisationsToDelete = ""; List organisationsIds = new ArrayList(); // create string with id`s values to delete organisations references while (resultSet.next()) { String actualValue = resultSet.getString("id"); organisationsIds.add(actualValue); } for (int i = 0; i < organisationsIds.size(); i++) { organisationsToDelete = " " + organisationsToDelete + organisationsIds.get(i); if (i != organisationsIds.size() - 1) { organisationsToDelete = organisationsToDelete + ", "; } } stmt.executeUpdate(" DELETE FROM `DB1`.`table1` WHERE `DB1`.`table1`.`organisation_id` in ( " + organisationsToDelete + " );"); } catch (SQLException e) { e.printStackTrace(); } finally { closeConnections(); } } public static List getOrganisationsDBNamesBySubdomain(String organisationsLike) { List organisationDbNames = new ArrayList(); ResultSet resultSet = executeMyQuery("select `DB`.organisation.dbname from `DB1`.organisation where subdomain like '" + organisationsLike + "%'", "DB1"); try { while (resultSet.next()) { String actualValue = resultSet.getString("dbname"); organisationDbNames.add(actualValue); } } catch (SQLException e) { e.printStackTrace(); } finally { closeConnections(); } return organisationDbNames; } public static List getAllDBNames() { // get all live db names incentral DB List organisationDbNames = new ArrayList(); ResultSet resultSet = executeMyQuery("show databases", "DB1"); try { while (resultSet.next()) { String actualValue = resultSet.getString("Database"); organisationDbNames.add(actualValue); } } catch (SQLException e) { e.printStackTrace(); } finally { closeConnections(); } return organisationDbNames; } public static void deleteDataBasesByName(List DataBasesNamesList) { try { connectSSH(); int dataBasesAmount = DataBasesNamesList.size(); for (int i = 0; i < dataBasesAmount; i++) { connectToDataBase(DataBasesNamesList.get(i)); Statement stmt = connection.createStatement(); stmt.executeUpdate("DROP database `" + DataBasesNamesList.get(i) + "`"); } } catch (SQLException e) { e.printStackTrace(); } finally { CloseDataBaseConnection(); closeConnections(); } } } 

Прежде всего, спасибо вам отлично!

Хотя, интересно, следует ли мне повторно использовать этот сеанс для каждого (потенциально одновременного) SQL-соединения или если я каждый раз создаю новый сеанс и обновляю его, только если по какой-то причине он истек.

В настоящее время я каждый раз, когда я создаю соединение, создаю новый экземпляр этого controllerа здесь, а затем выполняю SQL-запросы с соединением, которое я получил от него, а затем закройте его вручную.

Было бы неплохо, если бы я мог использовать class с try-with-resource и закрывать его. Посмотрите на это. Потому что я не хочу пропустить его.

Так выглядит то, что я сейчас получаю DB Connections.

 public class ConnectionManager { private Connection con = null; private Session session = null; public Connection getConnection() { Connection con = null; var settings = new DbSettingsController(); boolean useSSH = settings.getSetting(SettingKey.UseSSH).equals("true"); String sshPort = settings.getSetting(SettingKey.SSHPort); String sqlIp = settings.getSetting(SettingKey.MySqlIP); String sqlPort = settings.getSetting(SettingKey.MySqlPort); if(useSSH) { JSch jSch = new JSch(); try { this.session = jSch.getSession(settings.getSetting(SettingKey.SSHUser), settings.getSetting(SettingKey.SSHHost), Integer.valueOf(sshPort)); this.session.setPassword(settings.getSetting(SettingKey.SSHPassword)); this.session.setConfig("StrictHostKeyChecking", "no"); this.session.connect(); this.session.setPortForwardingL(Integer.parseInt(sshPort), sqlIp, Integer.parseInt(sqlPort)); } catch (JSchException e) { e.printStackTrace(); } } var connectionString = String.format("jdbc:mysql://%s:%s/%s?autoReconnect=true&useSSL=false", sqlIp, useSSH ? sshPort : sqlPort, settings.getSetting(SettingKey.MySqlShema)); var user = settings.getSetting(SettingKey.MySqlUser); var password = settings.getSetting(SettingKey.MySqlPassword); try { con = DriverManager.getConnection(connectionString, user, password); } catch (SQLException e) { e.printStackTrace(); } return con; } public void close() { if(this.con != null) { try { this.con.close(); } catch (SQLException e) { e.printStackTrace(); } } if(this.session != null) { this.session.disconnect(); } } 

Если вы задаетесь вопросом о DbSettingsController, я тоже сделал себя, просто помещал настройки в столбец Text в локальном DB SQLite с назначенным ему ключом (это значение enum’s int). Был только код копирования, который я использовал повторно из какого-либо другого проекта, поэтому было просто и быстро сделать это именно так.

  • Как изменить оболочку по умолчанию на удаленном сервере?
  • Как иметь несколько окон в сеансе терминала SSH?
  • Передача портов туннелирования ssh
  • Установите ресурс SSH как обычный жесткий диск под окнами
  • Оставить скрипт bash на удаленном терминале, пока он не вошел в систему?
  • ITerm2 теряет цвета «ls», если я ssh на сервере
  • Могу ли я создать файл конфигурации для сценария оболочки?
  • SSH по-прежнему запрашивает пароль после настройки проверки подлинности на основе ключа
  • SSH не будет работать в новой версии OS X 10.8.4
  • Продолжить фоновые задания / задания SSH при закрытии SSH
  • SSH для Cygwin медленно реагирует
  • Давайте будем гением компьютера.