JDBC經過SSH Tunnel鏈接MySQL數據庫

有時候咱們沒法直接訪問某臺數據庫,由於沒有受權或者ip限制,可是能夠經過登錄其餘機器來訪問,若是這臺服務器安裝有SSH,就能夠方便的在本地經過該服務的端口映射來代理訪問數據庫。Navicat就有這個方便的功能,以下圖所示: html

由此聯想到,在Java代碼中可否實現相似的功能呢? java

參考OSC上的這個問題:http://www.oschina.net/question/125831_79245 mysql

紅薯已經給出了連接,固然,在google上搜索排第一的也是stackoverflow上的回答:http://sina.lt/gUe linux

SSH自帶有端口轉發的命令,可將本地的任意可用端口轉發到遠程服務器的其餘端口: sql

ssh -L 1234:localhost:3306 mysql.server.remote
JScH就是一個實現了SSH2協議的Java包,示例代碼以下:

import java.sql.*;

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://sina.lt/gUh 服務器

SSH對主機的public_key的檢查等級是根據StrictHostKeyChecking變量來配置的。默認狀況下,StrictHostKeyChecking=ask。簡單所下它的三種配置值:                                          1.StrictHostKeyChecking=no #最不安全的級別,固然也沒有那麼多煩人的提示了,相對安全的內網測試時建議使用。若是鏈接server的key在本地不存在,那麼就自動添加到文件中(默認是known_hosts),而且給出一個警告。                   2.StrictHostKeyChecking=ask #默認的級別,就是出現剛纔的提示了。若是鏈接和key不匹配,給出提示,並拒絕登陸。                                                                                                                    3.StrictHostKeyChecking=yes #最安全的級別,若是鏈接與key不匹配,就拒絕鏈接,不會提示詳細信息。

2.關於JSch的網站,還有不少其餘協議的Java實現,好比SFTP,用於加密的ftp鏈接等等,參見代碼:http://www.jcraft.com/jsch/examples/Sftp.java session

3.關於SSH端口轉發,參見經過SSH實現端口映射 app

工做原理是這樣的, 本地機器上分配了一個 socket 偵聽 port 端口, 一旦這個端口上有了鏈接, 該鏈接就通過安全通道轉發出去, 同時遠程主機和 host 的 hostport 端口創建鏈接. 能夠在配置文件中指定端口的轉發. 只有 root 才能轉發特權端口.

另見實戰 SSH 端口轉發SSH端口轉發

EOF.

相關文章
相關標籤/搜索