1. 程式人生 > >使用JSCH連線時,需要輸入密碼的解決方法

使用JSCH連線時,需要輸入密碼的解決方法

背景:

在做一個安裝指令碼,期間會執行一些資料庫的操作,需要DBA帳號才可以執行。

我們用的JSCH建立SSH通道,直接連線到目標機器上執行,效果和開啟命令列是一樣的,唯一特殊的,就是關於DBA的密碼的問題。

Oracle(我們的資料庫用的Oracle)的指令碼中是提供了連同密碼一起輸入的功能的,但是!凡事就怕但是!客戶提出的要求是:對帳號密碼的明文儲存零容忍!

Ok,說白了,不能在配置檔案裡把DBA密碼寫進去,然後批量執行。必須在Oracle'提示輸入密碼的時候,輸入之。

問題:

JSCH提供的原始的幾個channel,還是比較直接的。 常用的有SFTP/ChannelShell/ChannelExec。為了取環境變數方便,我們用了ChannelShell。

ChannelShell是可以設定InputStream和OutputStream的。

但是輸入密碼只能從console輸入,所以channelshell.setInputStream(System.in)麼?

但是其他命令是從配置檔案輸入的,所以channelshell.setInputStream(new FileInputStream(filename))麼?

無論如何,只能設定一個InputStream,怎麼兼顧?

調查:

第一步,google之。 有幾個文章參考了,但是不合適。

第二步,嘗試使用Except4J,不過它也是全指令碼的,不能中間切換到System.in.

第三步,就是按照Except4J的做法,自己控制JSCH的input/output stream。 於是有了此文。

方案:

前面說了那麼多廢話,其實目的就是一個:把來龍去脈介紹一下,或許有大俠發現我幹了個重複的事情,有更好的方案,可以給我指教一下。

如果也被這個問題困擾的話,可以看看,一起討論下。

我的方法就是:

自己寫InputStream和OutputStream,然後把它們設定到JSCH的channelshell裡去,這樣它就會從我這裡讀寫了

然後呢,讀的時候就從我的檔案裡讀,我告訴它輸入是“xyz”它就拿到xyz;

寫的時候呢,它就寫到我的outputstream裡,我就知道結果是ABC啦。

有了以上兩個前提,那麼我再加一些小功能:

1. 讀檔案的時候,我多寫一些配置資訊,發現現在是password,那我就從System.in讀資料,然後發給JSCH channel;

2. 獲得response的時候,我判斷是否和我期望的結果一樣,然後我再執行下一條。

 於是就有了這個配置檔案:

## This file format just for POC, you can define yours.
## For my format, it is:
## 1. # starts for comments
## 2. There are 3 parts: [<expect>]<type>[<content>]
## 3. For <expect>, it's easy: [$] means you expect a '$' ends;
## 4. For <type>, support 'send' and 'password'. 
##    If 'send', means the <content> will be send to SSH channel. 
##    If 'password', means the <content> come from system console, that is, need you type in.

[$]send[pwd]
[$]send[whoami]
[$]send[su - root]
[Password:]password[]
[#]send[pwd]
[#]send[ls]
[#]send[whoami]
[#]send[exit]
[$]send[ls]
[$]send[pwd]
[$]send[whoami]
[$]send[su - root]
[Password:]password[]
[#]send[pwd]
[#]send[ls]
[#]send[whoami]
[#]send[exit]
[$]send[exit]

原理就是這樣了,很簡單的苦力活。