Django3 使用 WebSocket 实现 WebShell( 二 )

缝合怪做为合格的代码搬运工,为了提高搬运效率还是要造点轮子填点坑的,如何将上面的 WebSocket 类与 paramiko 结合起来,实现从前端接受字符传递给远程主机,并同时接受返回呢?
【Django3 使用 WebSocket 实现 WebShell】import asyncioimport tracebackimport paramikofrom webshell.ssh import Base, RemoteSSHfrom webshell.connection import WebSocketclass WebShell:"""整理 WebSocket 和 paramiko.Channel,实现两者的数据互通"""def __init__(self, ws_session: WebSocket,ssh_session: paramiko.SSHClient = None,chanel_session: paramiko.Channel = None):self.ws_session = ws_sessionself.ssh_session = ssh_sessionself.chanel_session = chanel_sessiondef init_ssh(self, host=None, port=22, user="admin", passwd="admin@123"):self.ssh_session, self.chanel_session = RemoteSSH(host, port, user, passwd).session()def set_ssh(self, ssh_session, chanel_session):self.ssh_session = ssh_sessionself.chanel_session = chanel_sessionasync def ready(self):await self.ws_session.accept()async def welcome(self):# 展示linux欢迎相关内容for i in range(2):if self.chanel_session.send_ready():message = self.chanel_session.recv(2048).decode('utf-8')if not message:returnawait self.ws_session.send_text(message)async def web_to_ssh(self):# print('--------web_to_ssh------->')while True:# print('--------------->')if not self.chanel_session.active or not self.ws_session.status:returnawait asyncio.sleep(0.01)shell = await self.ws_session.receive_text()# print('-------shell-------->', shell)if self.chanel_session.active and self.chanel_session.send_ready():self.chanel_session.send(bytes(shell, 'utf-8'))# print('--------------->', "end")async def ssh_to_web(self):# print('<--------ssh_to_web-----------')while True:# print('<-------------------')if not self.chanel_session.active:await self.ws_session.send_text('ssh closed')returnif not self.ws_session.status:returnawait asyncio.sleep(0.01)if self.chanel_session.recv_ready():message = self.chanel_session.recv(2048).decode('utf-8')# print('<---------message----------', message)if not len(message):continueawait self.ws_session.send_text(message)# print('<-------------------', "end")async def run(self):if not self.ssh_session:raise Exception("ssh not init!")await self.ready()await asyncio.gather(self.web_to_ssh(),self.ssh_to_web())def clear(self):try:self.ws_session.close()except Exception:traceback.print_stack()try:self.ssh_session.close()except Exception:traceback.print_stack()前端xterm.js 完全满足,搜索下找个看着简单的就行 。
export class Term extends React.Component {private terminal!: HTMLDivElement;private fitAddon = new FitAddon();componentDidMount() {const xterm = new Terminal();xterm.loadAddon(this.fitAddon);xterm.loadAddon(new WebLinksAddon());// using wss for https//const socket = new WebSocket("ws://" + window.location.host + "/api/v1/ws");const socket = new WebSocket("ws://localhost:8000/webshell/");// socket.onclose = (event) => {//this.props.onClose();// }socket.onopen = (event) => {xterm.loadAddon(new AttachAddon(socket));this.fitAddon.fit();xterm.focus();}xterm.open(this.terminal);xterm.onResize(({ cols, rows }) => {socket.send("<RESIZE>" + cols + "," + rows)});window.addEventListener('resize', this.onResize);}componentWillUnmount() {window.removeEventListener('resize', this.onResize);}onResize = () => {this.fitAddon.fit();}render() {return <div className="Terminal" ref={(ref) => this.terminal = ref as HTMLDivElement}></div>;}}好了,废话不多少了,代码我放这里了webshell (
https://github.com/aleimu/webshell) 欢迎star/fork!




推荐阅读