有時候咱們沒法直接訪問某臺數據庫,由於沒有受權或者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.remoteJScH就是一個實現了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 才能轉發特權端口.
EOF.