SSHJ是一個開源 Java 庫,它使用SSH協議與遠端伺服器進行安全通訊。
在本文中,我們將介紹 SSHJ 庫的基本功能。
依賴關係
要使用 SSHJ 庫,我們必須將以下依賴項新增到專案中:
<dependency> <groupId>com.hierynomus</groupId> <artifactId>sshj</artifactId> <version>0.38.0</version> </dependency>
|
我們可以在 Maven Central 中找到最新版本的SSHJ庫。SSHJ庫
SSHJ 庫幫助透過 SSH 建立與遠端伺服器的安全連線。
藉助SSHJ 庫,我們可以使用 SCP 或 SFTP 協議處理檔案上傳和下載。另外,我們還有一個額外的好處,那就是能夠使用它進行本地埠轉發和遠端埠轉發。
連線SSH客戶端
SSH 客戶端可以使用密碼或公鑰身份驗證連線到伺服器。 SSHJ 庫使我們能夠使用任一方法登入。
1.密碼認證
我們可以使用 SSHJ 庫透過 SSH 埠連線到伺服器。需要為 SSH 連線指定主機名、埠、使用者名稱和密碼。
SSH 客戶端使用authPassword()方法透過密碼身份驗證連線到伺服器:
String host = <font>// ...<i> int port = // ...<i> String username = // ...<i> String password = // ...<i> SSHClient client = new SSHClient(); client.addHostKeyVerifier(new PromiscuousVerifier()); client.connect(host, port); client.authPassword(username, password);
|
正如我們在上面的程式碼中看到的,我們使用密碼身份驗證將客戶端連線到主機。2.公鑰認證
我們也可以使用公鑰連線到伺服器。為了使用公鑰進行連線,我們需要在伺服器上的known_hosts檔案中有一個檔案條目,或者我們可以在客戶端計算機上為遠端伺服器生成一個公鑰,並將公鑰複製到伺服器上的授權SSH金鑰中。
SSH 客戶端使用authPublickey()方法透過公鑰身份驗證連線到伺服器:
String host = <font>// ... <i> String username = // ... <i> File privateKeyFile = // ... <i> int port = // ...<i> SSHClient client = new SSHClient(); KeyProvider privateKey = client.loadKeys(privateKeyFile.getPath()); client.addHostKeyVerifier(new PromiscuousVerifier()); client.connect(host, port); client.authPublickey(username, privateKey);
|
我們可以為客戶端生成一個公鑰,並在要連線的伺服器上更新它。在其餘示例中,我們將使用第一種方法登入,即使用使用者名稱和密碼。透過 SSH 執行命令
我們可以在連線到伺服器的sshClient 啟動的會話 上使用exec()方法透過 SSHJ 庫執行命令:
SSHClient client = new SSHClient(); Session session = sshClient.startSession(); Command cmd = session.exec(<font>"ls -lsa"); BufferedReader reader = new BufferedReader(new InputStreamReader(cmd.getInputStream())); String line; while ((line = reader.readLine()) != null) { System.out.println(line); } cmd.join(5, TimeUnit.SECONDS); session.close();
|
正如我們在上面的程式碼中看到的,我們為sshClient啟動一個會話。然後,我們執行ls -lsa命令,該命令列出了目錄中的所有檔案。然後,我們使用BufferedReader來讀取所執行命令的輸出。同樣,這裡也可以執行其他命令。
透過SCP上傳/下載檔案
我們可以透過SCP上傳檔案。對於上傳,我們使用SCPFileTransfer物件的upload()方法:
String filePath = <font>// ... <i> SSHClient ssh = new SSHClient(); ssh.useCompression(); ssh.newSCPFileTransfer() .upload(new FileSystemFile(filePath), "/upload/");
|
在這裡,我們將檔案傳輸到伺服器上的上傳目錄。useCompression()方法將zlib壓縮新增到首選演算法中,這可以顯著提高速度。無法保證談判會成功。如果客戶端已經連線,則重新協商;否則,它只會返回。我們也可以在連線客戶端之前使用useCompression() 。
對於 SCP 檔案下載,我們在SCPFileTransfer物件上使用download() 方法:
String downloadPath = <font>// ...<i> String fileName = // ...<i> SSHClient ssh = new SSHClient(); ssh.useCompression(); ssh.newSCPFileTransfer() .download("/upload/" + fileName, downloadPath);
|
在這裡,我們將檔案從伺服器上的upload目錄下載到客戶端上的downloadPath位置。上述上傳和下載方法在內部執行scp命令,使用 SSH 連線將檔案從本地計算機複製到遠端伺服器,反之亦然。
透過SFTP上傳/下載檔案
我們可以透過SFTP上傳檔案。對於上傳,我們使用SFTPClient物件上的put()方法:
String filePath = <font>// ...<i> SSHClient ssh = new SSHClient(); SFTPClient sftp = ssh.newSFTPClient(); sftp.put(new FileSystemFile(filePath), "/upload/");
|
這裡,我們將檔案從客戶端上的使用者主目錄傳輸到伺服器上的上傳目錄。對於 SFTP 下載,我們使用SFTPClient物件上的get() 方法:
String downloadPath = <font>// ...<i> String fileName = // ...<i> SSHClient ssh = new SSHClient(); SFTPClient sftp = ssh.newSFTPClient(); sftp.get("/upload/" + fileName, downloadPath); sftp.close();
|
在這裡,我們將檔案從伺服器上的upload目錄下載到客戶端上的downloadPath位置。本地埠轉發
本地埠轉發用於訪問遠端伺服器上的服務,就像服務在客戶端上執行一樣:
SSHClient ssh = new SSHClient(); Parameters params = new Parameters(ssh.getRemoteHostname(), 8081, <font>"google.com", 80); ServerSocket ss = new ServerSocket(); ss.setReuseAddress(true); ss.bind(new InetSocketAddress(params.getLocalHost(), params.getLocalPort())); ssh.newLocalPortForwarder(params, ss) .listen();
|
在這裡,我們將伺服器的80埠轉發到客戶端計算機的8081埠,以便我們可以從客戶端計算機上的8081埠訪問伺服器80埠上託管的網站或服務。遠端埠轉發
使用遠端埠轉發,我們可以將客戶端計算機上執行的服務公開到遠端伺服器網路:
SSHClient ssh = new SSHClient(); ssh.getConnection() .getKeepAlive() .setKeepAliveInterval(5); ssh.getRemotePortForwarder() .bind(new Forward(8083), new SocketForwardingConnectListener(new InetSocketAddress(<font>"google.com", 80))); ssh.getTransport() .join();
|
這裡,我們將執行在客戶端8083埠的服務轉發到遠端伺服器的80埠。實際上,在客戶端計算機上的8083埠上執行的服務暴露在遠端伺服器的80埠上。對於本地和遠端埠轉發,我們需要確保正確的防火牆設定到位。
檢查連線丟失
我們需要檢查連線丟失以監控伺服器連線狀態和健康狀況。 SSHJ 提供了使用 keepalive 檢查連線丟失的選項:
String hostName = <font>// ...<i> String userName = // ...<i> String password = // ...<i> DefaultConfig defaultConfig = new DefaultConfig(); defaultConfig.setKeepAliveProvider(KeepAliveProvider.KEEP_ALIVE); SSHClient ssh = new SSHClient(defaultConfig); ssh.addHostKeyVerifier(new PromiscuousVerifier()); ssh.connect(hostName, 22); ssh.getConnection() .getKeepAlive() .setKeepAliveInterval(5); ssh.authPassword(userName, password); Session session = ssh.startSession(); session.allocateDefaultPTY(); new CountDownLatch(1).await(); session.allocateDefaultPTY(); session.close(); ssh.disconnect();
|
在上面的程式碼中,我們可以看到配置KeepAliveProvider.KEEP_ALIVE啟用了SSHJ庫的保活模式。我們使用setKeepAliveInterval()來設定來自客戶端的兩個保持活動訊息之間的間隔。