在Java應用中嵌入sshd服務
阿新 • • 發佈:2019-02-05
這個應用需要依賴apache mina的子專案sshd,專案主頁http://mina.apache.org/sshd-project/index.html,當前版本號為0.8.0。這裡的sshd和Linux下的sshd服務在特性上類似,但卻是使用純Java語言實現的,為Java應用提供了自定義ssh協議接入的能力。相關的API使用比較簡單,見如下程式碼樣例,API的含義也在註釋中做了簡單的說明。由於我在家沒有Linux環境,因而只在Windows平臺做了簡單的試驗,比如使用者登入、校驗口令等,但不能體驗sftp接入控制的實現。
package com.sftp; import java.io.IOException; import java.util.EnumSet; import org.apache.sshd.SshServer; import org.apache.sshd.common.Session; import org.apache.sshd.common.util.OsUtils; import org.apache.sshd.common.util.SecurityUtils; import org.apache.sshd.server.FileSystemFactory; import org.apache.sshd.server.FileSystemView; import org.apache.sshd.server.PasswordAuthenticator; import org.apache.sshd.server.SshFile; import org.apache.sshd.server.keyprovider.PEMGeneratorHostKeyProvider; import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider; import org.apache.sshd.server.session.ServerSession; import org.apache.sshd.server.shell.ProcessShellFactory; public class SshdServer { public static void main(final String[] args) throws Exception { final SshServer sshd = SshServer.setUpDefaultServer();// 工廠方法,使用預設屬性建立ssh服務物件 if (SecurityUtils.isBouncyCastleRegistered()) {// 儲存會話安全校驗資訊,key.pem和key.ser為檔名 sshd.setKeyPairProvider(new PEMGeneratorHostKeyProvider("key.pem")); } else { sshd.setKeyPairProvider(new SimpleGeneratorHostKeyProvider("key.ser")); } if (OsUtils.isUNIX()) { // 在Unix環境下,使用系統自帶的sh來執行命令 sshd.setShellFactory(new ProcessShellFactory(new String[] { "/bin/sh", "-i", "-l" }, EnumSet .of(org.apache.sshd.server.shell.ProcessShellFactory.TtyOptions.ONlCr))); } else { // 在Windows平臺下,只能使用標準的cmd命令 sshd.setShellFactory(new ProcessShellFactory(new String[] { "cmd.exe " }, EnumSet.of( org.apache.sshd.server.shell.ProcessShellFactory.TtyOptions.Echo, org.apache.sshd.server.shell.ProcessShellFactory.TtyOptions.ICrNl, org.apache.sshd.server.shell.ProcessShellFactory.TtyOptions.ONlCr))); }
// 在Windows平臺,如果安裝了Cygwin,還可以使用如下的呼叫,把使用者的輸入委託給Cygwin的shell sshd.setShellFactory(new ProcessShellFactory(new String[] { "D:\\cygwin\\bin\\bash", "-i", "-l" })); sshd.setPasswordAuthenticator(new PasswordAuthenticator() { // 使用使用者名稱和口令方式,自定義對接入使用者的校驗 public boolean authenticate(final String username, final String password, final ServerSession serversession) {
// 我本地的測試程式碼只是為了演示使用方法,所以只是簡單實現,對於一切來訪使用者都大開綠燈 return true; } }); sshd.setHost("127.0.0.1");// 指定提供ssh服務的IP sshd.setPort(2022); // 指定ssh服務的埠,為了避免影響系統的服務,這裡使用了自定義的2022埠 sshd.setFileSystemFactory(new FileSystemFactory() {// 如果需要使用ssh協議來提供檔案下載、上傳能力,則需要實現FileSystemFactory和SshFile介面 public FileSystemView createFileSystemView(final Session session) throws IOException { return new FileSystemView() { public SshFile getFile(final SshFile sshfile, final String s) { return null; } public SshFile getFile(final String s) { return null; } }; } }); sshd.start();// 啟動ssh服務 } }
使用自定義的ssh服務有如下幾點好處:
1、不需要建立作業系統的賬號。在Linux環境下,如果要使用預設的ssh服務,事先需要建立一個作業系統的賬號,這樣存在安全隱患,對於心存惡意的來訪者,系統被攻破只是時間問題;
2、可以通過實現FileSytemFactory介面和SshFile介面控制來訪使用者通過sftp訪問到的目錄及檔案列表,避免來訪者對無權路徑的訪問;
不過這個專案當前版本號為0.8.0,可以說非常年輕,在商用的產品中使用時,需要考慮風險。