1. 程式人生 > >JDBC通過SSH Tunnel連線MySQL資料庫

JDBC通過SSH Tunnel連線MySQL資料庫

有時候我們無法直接訪問某臺數據庫,因為沒有授權或者ip限制,但是可以通過登陸其他機器來訪問,如果這臺伺服器安裝有SSH,就可以方便的在本地通過該服務的埠對映來代理訪問資料庫。Navicat就有這個方便的功能,如下圖所示:

由此聯想到,在Java程式碼中能否實現類似的功能呢?

紅薯已經給出了連結,當然,在google上搜索排第一的也是stackoverflow上的回答:http://go.rritw.com/sina.lt/gUe

SSH自帶有埠轉發的命令,可將本地的任意可用埠轉發到遠端伺服器的其他埠:

ssh -L 1234:localhost:3306 mysql.server.
remote
JScH就是一個實現了SSH2協議的Java包,示例程式碼如下: 
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;

import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;

public class TestJSch {

	static int lport = 3306;//本地埠
	static String rhost = "10.10.10.10";//遠端MySQL伺服器
	static int rport = 3306;//遠端MySQL服務埠

	public static void go() {
		String user = "username";//SSH連線使用者名稱
		String password = "password";//SSH連線密碼
		String host = "10.10.10.11";//SSH伺服器
		int port = 2222;//SSH訪問埠
		try {
			JSch jsch = new JSch();
			Session session = jsch.getSession(user, host, port);
			session.setPassword(password);
			session.setConfig("StrictHostKeyChecking", "no");
			session.connect();
			System.out.println(session.getServerVersion());//這裡列印SSH伺服器版本資訊
			int assinged_port = session.setPortForwardingL(lport, rhost, rport);
			System.out.println("localhost:" + assinged_port + " -> " + rhost + ":" + rport);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public static void sql() {
		Connection conn = null;
		ResultSet rs = null;
		Statement st = null;
		try {
			Class.forName("com.mysql.jdbc.Driver");
			conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "");
			st = conn.createStatement();
			String sql = "SELECT COUNT(1) FROM All";
			rs = st.executeQuery(sql);
			while (rs.next())
				System.out.println(rs.getString(1));
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			//rs.close();st.close();conn.close();
		}
	}

	public static void main(String[] args) {
		go();
		sql();
	}
}

從而連線SSH後,通過訪問本地的3306埠就被指向了 10.10.10.10伺服器的3306埠,就好像MySQL安裝在本地一樣。前提是SSH伺服器10.10.10.11能夠訪問MySQL資料庫伺服器10.10.10.10的3306端口才能做轉發。

P.S.

1.關於SSH連線中的StrictHostKeyChecking引數manpage解釋為:該選項可被用於阻止未知的或更改過的host key的登陸。參見:http://go.rritw.com/sina.lt/gUh

SSH對主機的public_key的檢查等級是根據StrictHostKeyChecking變數來配置的。預設情況下,StrictHostKeyChecking=ask。簡單所下它的三種配置值:                                          1.StrictHostKeyChecking=no #最不安全的級別,當然也沒有那麼多煩人的提示了,相對安全的內網測試時建議使用。如果連線server的key在本地不存在,那麼就自動新增到檔案中(預設是known_hosts),並且給出一個警告。 2.StrictHostKeyChecking=ask #預設的級別,就是出現剛才的提示了。如果連線和key不匹配,給出提示,並拒絕登入。                                                                                                                    3.StrictHostKeyChecking=yes #最安全的級別,如果連線與key不匹配,就拒絕連線,不會提示詳細資訊。
工作原理是這樣的, 本地機器上分配了一個 socket 偵聽 port 埠, 一旦這個埠上有了連線, 該連線就經過安全通道轉發出去, 同時遠端主機和 host 的 hostport 埠建立連線. 可以在配置檔案中指定埠的轉發. 只有 root 才能轉發特權埠.

EOF.