先看看telnet 和ssh的定義:
Telnet協議是TCP/IP協議中的一員,是Internet遠程登陸服務的標準協議和主要方式。它爲用戶提供了在本地計算機上完成遠程主機工作的能力。在終端使用者的電腦上使用telnet程序,用它連接到服務器。終端使用者可以在telnet程序中輸入命令,這些命令會在服務器上運行,就像直接在服務器的控制檯上輸入一樣。可以在本地就能控制服務器。要開始一個telnet會話,必須輸入用戶名和密碼來登錄服務器。Telnet是常用的遠程控制Web服務器的方法。
SSH是一個用來替代TELNET、FTP以及R命令的工具包,主要是想解決口令在網上明文傳輸的問題。爲了系統安全和用戶自身的權益,推廣SSH是必要的。 SSH是英文Secure Shell的簡寫形式。通過使用SSH,你可以把所有傳輸的數據進行加密,這樣"中間人"這種攻擊方式就不可能實現了,而且也能夠防止DNS欺騙和IP欺騙。
實際上,telnet和ssh的功能基本相同,都是實現遠程登陸的網絡協議。
和其他多數協議一樣, java 中telnet ssh的實現也要經過三部曲:建立連接、使用連接 和釋放連接 。ssh是用以替換telnet 的一種協議,在java 編程中 ,ssh和telnet 的不同僅僅表現在建立連接和釋放連接中。
使用連接的過程,其實就是發送命令和遠程服務器交互的過程,原理也很簡單:每向服務器發送一條命令,就等待服務器執行此命令後返回的字符流,暫且把它叫做一次交互。我們以在規定時間內接收這些字符流,如果這些字符流中出現了“命令提示符”,說明服務器處於等待狀態,我們就認爲此次交互完成,否則,此次交互失敗,出現異常。
linux服務器上的命令提示符不多,登陸命令提示符就更有限了,一般就包括 用戶名提示符、密碼提示符 和登陸成功提示符(也叫命令提示符)這三類,不同linux的用戶命令提示符、密碼提示符也會稍有不同。
下面簡單寫一個程序做telnet的測試,此程序僅作測試,所以很多寫法並不規範。
(1)所需包:commons-net-2.2.jar
(2)代碼如下:
- package telnet;
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.OutputStream;
- import java.net.SocketException;
- import java.util.regex.Pattern;
- import org.apache.commons.net.telnet.TelnetClient;
- public class Telnet {
- private TelnetClient telnetClient;
- private InputStream inputStream;
- private OutputStream outputStream;
- private long timeout=30000;//默認超時爲30秒
- public void connect(String hostIp,int port,String userName,String password) throws SocketException, IOException{
- telnetClient=new TelnetClient();
- telnetClient.connect(hostIp, port);
- inputStream=telnetClient.getInputStream(); //接收服務器消息的輸入流
- outputStream=telnetClient.getOutputStream(); //發送消息到服務器的輸出流
- //連接完畢,服務器就等待客戶發送 用戶名,然後是密碼
- if(sendLoginInfo(userName,".*PASSWORD:")){//假如發送完用戶名後得到的提示符是密碼提示符
- sendLoginInfo(password, "//]//$"); //假如發送密碼信息後得到的提示符是命令提示符
- }
- }
- private boolean sendLoginInfo(String info,String regext){
- Pattern pattern=Pattern.compile(regext);
- try {
- outputStream.write((info+"/n").getBytes());
- outputStream.flush();
- int i=-1;
- StringBuilder sb=new StringBuilder();
- long startTime=System.currentTimeMillis();
- while(System.currentTimeMillis()-startTime
- while( (i=(char) inputStream.read())>-1){
- if(i==-1){
- throw new IllegalArgumentException("接收不到消息");
- }
- char ch=(char)i;
- if(ch=='/n'||ch=='/r'){ //命令提示符是最後在一行的
- sb.delete(0, sb.length());
- continue;
- }
- sb.append((char)ch);
- if(pattern.matcher(sb.toString()).find()){
- return true;
- }
- }
- }
- throw new IllegalArgumentException("超時收不到提示符");
- } catch (IOException e) {
- close();
- return false;
- }
- }
- public String send(String cmd){
- if(null==telnetClient||null==inputStream||null==outputStream){
- throw new IllegalArgumentException("請先 建立連接 或建立連接失敗");
- }
- Pattern pattern=Pattern.compile("//]//$");//假如命令提示符爲 /$
- StringBuilder text=new StringBuilder();
- try {
- outputStream.write((cmd+"/n").getBytes());
- outputStream.flush();
- StringBuilder sb=new StringBuilder();
- long startTime=System.currentTimeMillis();
- int i=-1;
- while(System.currentTimeMillis()-startTime
- while( (i=inputStream.read())>-1){
- if(i==-1){
- throw new IllegalArgumentException("接收不到消息");
- }
- char ch=(char)i;
- text.append(ch);
- if(ch=='/n'||ch=='/r'){
- sb.delete(0, sb.length());
- continue;
- }
- sb.append(ch);
- if(pattern.matcher(sb.toString()).find()){//返回字符流中找到了命令提示符
- return text.toString();
- }
- }
- }
- throw new IllegalArgumentException("超時收不到提示符");
- } catch (IOException e) {
- close();
- return null;
- }
- }
- public void close(){
- if(null!=null){
- try {
- telnetClient.disconnect();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
- public static void main(String[] args) throws SocketException, IOException {
- Telnet telnet=new Telnet();
- telnet.connect("ip" , 23, "username", "passowrd");
- System.out.println(telnet.send("ls"));
- telnet.close();
- }
- }
ssh 的實現和和 telnet 大同小異,差別在於建立連接和釋放連接:
(1)需要包:jsch-0.1.42.jar
(2) 關鍵代碼如下:
- public void connect(String hostIp,int port,String userName,String password){
- try {
- session=jsch.getSession(userName,hostIp,port );
- session.setPassword(password);
- session.setUserInfo(defaultUserInfo);
- session.connect();
- channel=session.openChannel("shell");
- inputStream=channel.getInputStream();
- outputStream=channel.getOutputStream();
- } catch (JSchException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- //關閉連接
- public void close(){
- if(null!=channel){
- channel.disconnect();
- }
- if(null!=session){
- session.disconnect();
- }
- }
其中 defaultUserInfo 是實現了UserInfo的一個類對象:
- UserInfo defaultUserInfo = new UserInfo() {
- public String getPassphrase() {
- return null;
- }
- public String getPassword() {
- return null;
- }
- public boolean promptPassword(String arg0) {
- return false;
- }
- public boolean promptPassphrase(String arg0) {
- return false;
- }
- public boolean promptYesNo(String arg0) {
- return true;
- }
- public void showMessage(String arg0) {
- }
- }