JavaWeb版 linux shell

效果图

后台Java代码
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import io.netty.channel.Channel;

import java.util.Map;

/**
* WebSocket接收到消息触发工具类
*/
public class WebSockedMsgUtils {
	public static Gson son = new Gson();

	public static void processMsg(Channel channel, String str){
		//Tools.checkHasNullParam 是自己写的非空判断
		if(Tools.checkHasNullParam(channel,str)){
			WebBaseMsg base = son.fromJson(str, WebBaseMsg.class);
			if(base != null){
				//SSH 初始化连接
				if("ssh-connection".equals(base.getType())) {
					Map<String, Object> param = Tools.getGson().fromJson(base.getMsgText(), new TypeToken<Map<String, Object>>(){}.getType());
					try {
						new SSHThread(channel.hashCode() + "", param.get("host") + "", ((Long) param.get("port")).intValue(), param.get("username") + "", param.get("password") + "").start();
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
				//执行命令
				else if("ssh-send-command".equals(base.getType())) {
					SSHUtil.execCmd(channel.hashCode() + "", base.getMsgText());
				}
				//SSH 断开连接
				else if("ssh-disconnection".equals(base.getType())) {
					if(SSHUtil.sshMap.containsKey(channel.hashCode() + "")) {
						SSHUtil.sshMap.get(channel.hashCode() + "").disconnect();
						SSHUtil.sshMap.remove(channel.hashCode() + "");
					}
				}
			}
		}
	}
}




//------------------------------------------------------------------------------------------
//给出部分的导入包路径
import com.jcraft.jsch.Channel;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;

import java.io.InputStream;
import java.util.Arrays;
import java.util.Properties;

/**
 * SSH工具类
 * @since 1.0.0
 */
public class SSHThread extends Thread {

	private String channelKey;
	private String host;
	private int    port;
	private String username;
	private String password;

	public SSHThread(String channelKey, String host, int port, String username, String password) {
		this.channelKey = channelKey;
		this.host       = host;
		this.port       = port;
		this.username   = username;
		this.password   = password;
	}

	@Override
	public void run() {
		try {
			Properties config = new Properties();
			config.put("StrictHostKeyChecking", "no");
			//获取jsch的会话
			JSch jSch = new JSch();
			Session session = jSch.getSession(username, host, port);
			session.setConfig(config);
			//设置密码
			session.setPassword(password);
			//连接  超时时间30s
			session.connect(10000);

			//开启shell通道
			Channel channel = session.openChannel("shell");

			//通道连接 超时时间3s
			channel.connect(3000);

			//设置channel
			SSHUtil.sshMap.put(channelKey, channel);

			//读取终端返回的信息流
			InputStream inputStream = channel.getInputStream();
			try {
				WebBaseMsg msg = new WebBaseMsg();
				msg.setType("ssh-receive");

				//发送已建立连接
				msg.setMsgText("Connection established.\r\n");
				ChannelMap.sendChannel(channelKey, Tools.gson.toJson(msg));

				//循环读取
				byte[] buffer = new byte[1024];
				int i = 0;
				//如果没有数据来,线程会一直阻塞在这个地方等待数据。
				while ((i = inputStream.read(buffer)) != -1) {
					msg.setMsgText(new String(Arrays.copyOfRange(buffer, 0, i)));
					ChannelMap.sendChannel(channelKey, Tools.gson.toJson(msg));
				}
			} finally {
				Log.info("断开 " + host + ":" + port + " SSH连接");
				//断开连接后关闭会话
				session.disconnect();
				channel.disconnect();
				if (inputStream != null) {
					inputStream.close();
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
			WebBaseMsg msg = new WebBaseMsg();
			msg.setType("equip-ssh-receive");
			msg.setMsgText(e.toString());
			ChannelMap.sendChannel(channelKey, Tools.gson.toJson(msg));
		}
	}
}




//------------------------------------------------------------------------------------------
import com.jcraft.jsch.Channel;

import java.io.OutputStream;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
 * SSH工具类
 * @since 1.0.0
 */
public class SSHUtil {

	/**
	 * SSH连接集合,Map<Socket Channel HashCode, SSH连接通道>
	 */
	public static Map<String, Channel> sshMap = new ConcurrentHashMap<>();

	/**
	 * 执行SSH命令
	 * @param channelKey
	 * @param cmd
	 */
	public static void execCmd(String channelKey, String cmd) {
		try {
			if (sshMap.containsKey(channelKey)) {
				OutputStream outputStream = sshMap.get(channelKey).getOutputStream();
				outputStream.write(cmd.getBytes());
				outputStream.flush();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}




//------------------------------------------------------------------------------------------
import io.netty.channel.Channel;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class ChannelMap {
	/**
	 * Map<ChannelHandlerContext HashCode, Channel>
	 */
	private static Map<String, Channel> map = new ConcurrentHashMap<>();

	/**
	 * 登录账号和通信道关联关系Map集合
	 * Map<ChannelHandlerContext HashCode, 登录账号ID>
	 */
	public static Map<String, Integer> userChannelLinkMap = new ConcurrentHashMap<>();

	public static void addChannel(String key, Channel c) {
		map.put(key, c);
	}
	
	/**
	 * Socket断开连接时触发
	 * @param key
	 */
	public static void removeChannel(String key) {
		//断开CPE的ssh连接
		if(SSHUtil.sshMap.containsKey(key)) {
			SSHUtil.sshMap.get(key).disconnect();
			SSHUtil.sshMap.remove(key);
		}
	}

	/**
	 * websocket推送消息
	 * @param msg
	 */
	public static void sendChannel(String channelKey, String msg) {
		Channel c = map.get(channelKey);
		if(c != null) {
			c.writeAndFlush(new TextWebSocketFrame(msg));
		}
		else{
			Log.info("web soket通道未连接成功,无法发送消息");
		}
	}
}




//------------------------------------------------------------------------------------------
/**
 * 基础消息类
 */
public class WebBaseMsg {
	private String type;//type类型可以从 WebBaseType里取
	//消息ID,必须唯一,用来获取返回值唯一标准
	private String msgId;
	private String msgText;

	/**日志类型的ID*/
	private String typeId;
	//初始化客户端id
	public WebBaseMsg() {
	}

	public WebBaseMsg(String type, String msgText) {
		super();
		this.type = type;
		this.msgText = msgText;
	}

	public String getTypeId() {
		return typeId;
	}

	public void setTypeId(String typeId) {
		this.typeId = typeId;
	}

	public String getMsgText() {
		return msgText;
	}

	public void setMsgText(String msgText) {
		this.msgText = msgText;
	}

	public String getMsgId() {
		return msgId;
	}

	public void setMsgId(String msgId) {
		this.msgId = msgId;
	}

	public String getType() {
		return type;
	}

	public void setType(String type) {
		this.type = type;
	}
}











//前端javascript代码
**使用 xterm.js 插件。**

var sshTerminal = null;
/**
 * 打开控制台
 */
function openSSHConsoleModal() {
	//清理结果集
	$("#sshConsoleParentDiv").html("");
	//---------------------------------------------
	//显示控制台,这个是自己封装的bootstrap弹出框方法,可以直接使用$("#id").modal("show");
	commons.setModalSize("sshConsoleModal", commons.getWindowWidth() * 0.8, 510);
	commons.showModal("sshConsoleModal", function () {
		sshTerminal = new Terminal({
			cols: 250,
			rows: 25,
			cursorBlink: true, // 光标闪烁
			cursorStyle: "block", // 光标样式  null | 'block' | 'underline' | 'bar'
			scrollback: 800, //回滚
			tabStopWidth: 8, //制表宽度
			screenKeys: true
		});

		sshTerminal.open(document.getElementById('sshConsoleParentDiv'));
		//在页面上显示连接中...
		sshTerminal.write("Connecting \r\n");

		//初始化SSH连接
		//这个是发送socket消息,需要自己去实现websocket连接后台的代码
		socketSend(commons.objectToJsonString({
			type   : "ssh-connection",
			msgText: commons.objectToJsonString({
				host    : "192.168.1.1",
				port    : 22,
				username: "root",
				password: "admin"
			})
		}));

		sshTerminal.on('data', function (data) {
			socketSend(commons.objectToJsonString({
				type   : "ssh-send-command",
				msgText: data
			}));
		});
	}, 
	//这个是自己封装的方法,关闭bootstrap modal时触发的。
	function () {
		//设置终端对象为空
		sshTerminal = null;
		//这个是自己封装的loading
		commons.loadingShow();
		//这个是发送socket消息
		socketSend(commons.objectToJsonString({
			type: "ssh-disconnection"
		}));
		//这个是自己封装的loading
		commons.loadingHide();
	});
}

/**
 * 重写Socket返回数据的回调方法
 * @param msg
 */
function socketCallback(msg) {
	var obj = JSON.parse(msg.data);
	if(obj.type = "ssh-receive") {
		if(sshTerminal != null) {
			console.log(obj.msgText);
			sshTerminal.write(obj.msgText);
		}
	}
}








<%--页面代码--%>
<%--SSH控制台--%>
<div class="modal fade common_model" id="sshConsoleModal" tabindex="-1" role="basic" aria-hidden="true">
	<div class="modal-dialog">
		<div class="modal-content" style="margin-top: 50px;">
			<div class="modal-header" style="background-color: #242424; margin-bottom: 0; border-bottom: 1px solid #504f4f; padding: 10px; border-top-left-radius: 0; border-top-right-radius: 0;">
				<button type="button" class="close" data-dismiss="modal"></button>
				<button type="button" style="float: right; margin-right: 20px; margin-top: -2px;" class="btn btn-xs grey-mint" onclick="openCpeSSHModal()">账号信息</button>
				<h4 class="modal-title" id="sshConsoleModalTitle" style="font-size: 14px;">SSH控制台</h4>
			</div>
			<div class="modal-body" style="background-color: #242424; color: #9a9a9a; padding: 5px;" id="sshConsoleCmdList">
				<div style="width: 100%;" id="sshConsoleParentDiv"></div>
			</div>
		</div>
	</div>
</div>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值