Java怎麼使用SSH連接服務器

    1.簡介

    SSH,也稱為安全外殼或安全套接字外殼,是一種網絡協議,允許一台計算機通過不安全的網絡安全地連接到另一台計算機。在本教程中,我們將展示如何使用JSch和Apache MINA SSHD庫通過Java與遠程SSH服務器建立連接

    在我們的示例中,我們將首先打開SSH連接,然後執行一個命令,讀取輸出並將其寫入控制台,最後關閉SSH連接。我們將使示例代碼盡可能簡單。

    2. JSch

    JSch是SSH2的Java實現,它使我們可以連接到SSH服務器並使用端口轉發,X11轉發和文件傳輸。而且,它已獲得BSD樣式許可的許可,並為我們提供了一種與Java建立SSH連接的簡便方法。

    首先,讓我們將JSch Maven依賴項添加到我們的pom.xml文件中:

    <dependency>
    
     <groupId>com.jcraft</groupId>
    
     <artifactId>jsch</artifactId>
    
     <version>0.1.55</version>
    
     </dependency>

    2.1 實現方式

    要使用JSch建立SSH連接,我們需要一個用戶名,密碼,主機URL和SSH端口。默認的SSH端口是22,但是可能會發生這樣的情況,我們將服務器配置為使用其他端口進行SSH連接:

    public static void listFolderStructure(String username, String password,
    
     String host, int port, String command) throws Exception {
    
    
    
     Session session = null;
    
     ChannelExec channel = null;
    
    
    
     try {
    
     session = new JSch().getSession(username, host, port);
    
     session.setPassword(password);
    
     session.setConfig("StrictHostKeyChecking", "no");
    
     session.connect();
    
    
    
     channel = (ChannelExec) session.openChannel("exec");
    
     channel.setCommand(command);
    
     ByteArrayOutputStream responseStream = new ByteArrayOutputStream();
    
     channel.setOutputStream(responseStream);
    
     channel.connect();
    
    
    
     while (channel.isConnected()) {
    
     Thread.sleep(100);
    
     }
    
    
    
     String responseString = new String(responseStream.toByteArray());
    
     System.out.println(responseString);
    
     } finally {
    
     if (session != null) {
    
     session.disconnect();
    
     }
    
     if (channel != null) {
    
     channel.disconnect();
    
     }
    
     }
    
     }

    正如我們在代碼中看到的,我們首先創建一個客戶端會話並將其配置為連接到我們的SSH服務器。然後,我們創建一個用於與SSH服務器通信的客戶端通道,並在其中提供通道類型-在這種情況下為exec,這意味著我們將把Shell命令傳遞給服務器。

    另外,我們應該為將要寫入服務器響應的通道設置輸出流。使用channel.connect()方法建立連接後,將傳遞命令,並將接收到的響應寫入控制台。

    讓我們看看如何使用JSch提供的不同配置參數

    • StrictHostKeyChecking –指示應用程序是否將檢查是否可以在已知主機之間找到主機公鑰。另外,可用的參數值是askyes,no ,其中ask是默認值。如果我們將此屬性設置為yes ,那麼JSch將永遠不會將主機密鑰自動添加到known_hosts文件,並且它將拒絕連接主機密鑰已更改的主機。這將強制用戶手動添加所有新主機。如果將其設置為no ,那麼JSch將自動將新的主機密鑰添加到已知主機列表中
    • compression.s2c –指定是否對服務器到客戶端應用程序的數據流使用壓縮。可用值是zlibnone值,第二個是默認值
    • compression.c2s –指定是否在客戶端-服務器方向上對數據流使用壓縮。可用值是zlibnone值,第二個是默認值

    與服務器的通信結束後關閉會話和SFTP通道很重要,以避免內存洩漏

    3. Apache MINA SSHD

    Apache MINA SSHD為基於Java的應用程序提供SSH支持。該庫基於Apache MINA(一種可擴展的高性能異步IO庫)。

    讓我們添加Apache Mina SSHD Maven依賴項

    <dependency>
    
     <groupId>org.apache.sshd</groupId>
    
     <artifactId>sshd-core</artifactId>
    
     <version>2.5.1</version>
    
     </dependency>

    3.1 代碼實現

    讓我們看一下使用Apache MINA SSHD連接到SSH服務器的代碼示例:

    public static void listFolderStructure(String username, String password,
    
     String host, int port, long defaultTimeoutSeconds, String command) throws IOException {
    
    
    
     SshClient client = SshClient.setUpDefaultClient();
    
     client.start();
    
    
    
     try (ClientSession session = client.connect(username, host, port)
    
     .verify(defaultTimeoutSeconds, TimeUnit.SECONDS).getSession()) {
    
     session.addPasswordIdentity(password);
    
     session.auth().verify(defaultTimeoutSeconds, TimeUnit.SECONDS);
    
    
    
     try (ByteArrayOutputStream responseStream = new ByteArrayOutputStream();
    
     ClientChannel channel = session.createChannel(Channel.CHANNEL_SHELL)) {
    
     channel.setOut(responseStream);
    
     try {
    
     channel.open().verify(defaultTimeoutSeconds, TimeUnit.SECONDS);
    
     try (OutputStream pipedIn = channel.getInvertedIn()) {
    
     pipedIn.write(command.getBytes());
    
     pipedIn.flush();
    
     }
    
    
    
     channel.waitFor(EnumSet.of(ClientChannelEvent.CLOSED),
    
     TimeUnit.SECONDS.toMillis(defaultTimeoutSeconds));
    
     String responseString = new String(responseStream.toByteArray());
    
     System.out.println(responseString);
    
     } finally {
    
     channel.close(false);
    
     }
    
     }
    
     } finally {
    
     client.stop();
    
     }
    
     }

    使用Apache MINA SSHD時,我們的事件序列與JSch類似。首先,我們使用SshClient類實例建立與SSH服務器的連接。如果我們使用SshClient.setupDefaultClient(),對其進行初始化,那麼我們將能夠使用具有適合大多數用例的默認配置的實例。這包括密碼,壓縮,MAC,密鑰交換和簽名。

    在那之後,我們將創建ClientChannel並將ByteArrayOutputStream附加到它,以便將其用作響應流。如我們所見,SSHD需要為每個操作定義超時。它還允許我們使用Channel.waitFor()方法定義在命令傳遞後等待服務器響應的時間。

    請務必注意, SSHD會將完整的控制台輸出寫入響應流。 JSch僅使用命令執行結果來執行此操作。

    有關Apache Mina SSHD的完整文檔可在該項目的官方GitHub存儲庫中找到

    4。結論

    本文說明瞭如何使用兩個可用的Java庫(JSch和Apache Mina SSHD)與Java建立SSH連接。我們還展示瞭如何將命令傳遞到遠程服務器並獲得執行結果。另外,可以在GitHub上獲得完整的代碼示例。