精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

Django3 使用 WebSocket 實現 WebShell

系統 Linux
大致看了下覺得這不夠有趣,翻了翻 django 的官方文檔發現 django 原生是不支持 websocket 的,但 django3 之后支持了 asgi 協議可以自己實現 websocket 服務。

[[435235]]

 前言

最近工作中需要開發前端操作遠程虛擬機的功能,簡稱 WebShell。基于當前的技術棧為 react+django,調研了一會發現大部分的后端實現都是 django+channels 來實現 websocket 服務。

大致看了下覺得這不夠有趣,翻了翻 django 的官方文檔發現 django 原生是不支持 websocket 的,但 django3 之后支持了 asgi 協議可以自己實現 websocket 服務。

于是選定 gunicorn+uvicorn+asgi+websocket+django3.2+paramiko 來實現 WebShell。

實現 websocket 服務

使用 django 自帶的腳手架生成的項目會自動生成 asgi.py 和 wsgi.py 兩個文件,普通應用大部分用的都是 wsgi.py 配合 nginx 部署線上服務。

這次主要使用 asgi.py 實現 websocket 服務的思路大致網上搜一下就能找到,主要就是實現 connect/send/receive/disconnect 這個幾個動作的處理方法。

這里 How to Add Websockets to a Django App without Extra Dependencies就是一個很好的實例,但過于簡單……

思路 

  1. # asgi.py   
  2. import os  
  3. from django.core.asgi import get_asgi_application  
  4. from websocket_app.websocket import websocket_application  
  5. os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'websocket_app.settings')  
  6. django_application = get_asgi_application()  
  7. async def application(scope, receive, send):  
  8.     if scope['type'] == 'http':  
  9.         await django_application(scope, receive, send)  
  10.     elif scope['type'] == 'websocket':  
  11.         await websocket_application(scope, receive, send)  
  12.     else:  
  13.         raise NotImplementedError(f"Unknown scope type {scope['type']}")  
  14. # websocket.py  
  15. async def websocket_application(scope, receive, send):  
  16.     pass  
  1. # websocket.py  
  2. async def websocket_application(scope, receive, send):  
  3.     while True:  
  4.         event = await receive()  
  5.         if event['type'] == 'websocket.connect':  
  6.             await send({  
  7.                 'type': 'websocket.accept'  
  8.             })  
  9.         if event['type'] == 'websocket.disconnect':  
  10.             break  
  11.         if event['type'] == 'websocket.receive':  
  12.             if event['text'] == 'ping':  
  13.                 await send({  
  14.                     'type': 'websocket.send',  
  15.                     'text': 'pong!'  
  16.                 }) 

實現

上面的代碼提供了思路

其中最核心的實現部分我放下面: 

  1. class WebSocket:  
  2.     def __init__(self, scope, receive, send):  
  3.         self._scope = scope  
  4.         self._receive = receive  
  5.         self._send = send  
  6.         self._client_state = State.CONNECTING  
  7.         self._app_state = State.CONNECTING  
  8.     @property  
  9.     def headers(self):  
  10.         return Headers(self._scope)  
  11.     @property  
  12.     def scheme(self): 
  13.        return self._scope["scheme"]  
  14.     @property  
  15.     def path(self): 
  16.        return self._scope["path"]  
  17.     @property  
  18.     def query_params(self):  
  19.         return QueryParams(self._scope["query_string"].decode())  
  20.     @property  
  21.     def query_string(self) -> str:  
  22.         return self._scope["query_string"]  
  23.     @property  
  24.     def scope(self):  
  25.         return self._scope  
  26.     async def accept(self, subprotocol: str = None):  
  27.         """Accept connection.  
  28.         :param subprotocol: The subprotocol the server wishes to accept.  
  29.         :type subprotocol: str, optional  
  30.         """  
  31.         if self._client_state == State.CONNECTING:  
  32.             await self.receive()  
  33.         await self.send({"type": SendEvent.ACCEPT, "subprotocol": subprotocol}) 
  34.     async def close(self, code: int = 1000):  
  35.         await self.send({"type": SendEvent.CLOSE, "code": code})  
  36.     async def send(self, message: t.Mapping):  
  37.         if self._app_state == State.DISCONNECTED: 
  38.             raise RuntimeError("WebSocket is disconnected.")  
  39.         if self._app_state == State.CONNECTING:  
  40.             assert message["type"] in {SendEvent.ACCEPT, SendEvent.CLOSE}, (  
  41.                     'Could not write event "%s" into socket in connecting state.'  
  42.                     % message["type"]  
  43.             )  
  44.             if message["type"] == SendEvent.CLOSE:  
  45.                 self._app_state = State.DISCONNECTED  
  46.             else:  
  47.                 self._app_state = State.CONNECTED  
  48.         elif self._app_state == State.CONNECTED:  
  49.             assert message["type"] in {SendEvent.SEND, SendEvent.CLOSE}, (  
  50.                     'Connected socket can send "%s" and "%s" events, not "%s"'  
  51.                     % (SendEvent.SEND, SendEvent.CLOSE, message["type"])  
  52.             )  
  53.             if message["type"] == SendEvent.CLOSE:  
  54.                 self._app_state = State.DISCONNECTED  
  55.         await self._send(message)  
  56.     async def receive(self):  
  57.         if self._client_state == State.DISCONNECTED:  
  58.             raise RuntimeError("WebSocket is disconnected.")  
  59.         message = await self._receive()  
  60.         if self._client_state == State.CONNECTING:  
  61.             assert message["type"] == ReceiveEvent.CONNECT, (  
  62.                     'WebSocket is in connecting state but received "%s" event'  
  63.                     % message["type"]  
  64.             )  
  65.             self._client_state = State.CONNECTED  
  66.         elif self._client_state == State.CONNECTED:  
  67.             assert message["type"] in {ReceiveEvent.RECEIVE, ReceiveEvent.DISCONNECT}, (  
  68.                     'WebSocket is connected but received invalid event "%s".'  
  69.                     % message["type"]  
  70.             )  
  71.             if message["type"] == ReceiveEvent.DISCONNECT:  
  72.                 self._client_state = State.DISCONNECTED  
  73.         return message 

縫合怪

做為合格的代碼搬運工,為了提高搬運效率還是要造點輪子填點坑的,如何將上面的 WebSocket 類與 paramiko 結合起來,實現從前端接受字符傳遞給遠程主機,并同時接受返回呢? 

  1. import asyncio  
  2. import traceback  
  3. import paramiko  
  4. from webshell.ssh import Base, RemoteSSH  
  5. from webshell.connection import WebSocket   
  6. class WebShell:  
  7.     """整理 WebSocket 和 paramiko.Channel,實現兩者的數據互通"""  
  8.     def __init__(self, ws_session: WebSocket,  
  9.                  ssh_session: paramiko.SSHClient = None 
  10.                  chanel_session: paramiko.Channel = None  
  11.                  ):  
  12.         self.ws_session = ws_session  
  13.         self.ssh_session = ssh_session  
  14.         self.chanel_session = chanel_session  
  15.     def init_ssh(self, host=Noneport=22user="admin"passwd="admin@123"):  
  16.         self.ssh_session, self.chanel_session = RemoteSSH(host, port, user, passwd).session()  
  17.     def set_ssh(self, ssh_session, chanel_session):  
  18.         self.ssh_session = ssh_session  
  19.         self.chanel_session = chanel_session  
  20.     async def ready(self):  
  21.         await self.ws_session.accept()  
  22.     async def welcome(self):  
  23.         # 展示Linux歡迎相關內容  
  24.         for i in range(2):  
  25.             if self.chanel_session.send_ready():  
  26.                 message = self.chanel_session.recv(2048).decode('utf-8')  
  27.                 if not message:  
  28.                     return  
  29.                 await self.ws_session.send_text(message)  
  30.     async def web_to_ssh(self):  
  31.         # print('--------web_to_ssh------->')  
  32.         while True:  
  33.             # print('--------------->')  
  34.             if not self.chanel_session.active or not self.ws_session.status:  
  35.                 return  
  36.             await asyncio.sleep(0.01)  
  37.             shell = await self.ws_session.receive_text()  
  38.             # print('-------shell-------->', shell)  
  39.             if self.chanel_session.active and self.chanel_session.send_ready():  
  40.                 self.chanel_session.send(bytes(shell, 'utf-8'))  
  41.             # print('--------------->', "end")  
  42.     async def ssh_to_web(self):  
  43.         # print('<--------ssh_to_web-----------')  
  44.         while True:  
  45.             # print('<-------------------')  
  46.             if not self.chanel_session.active:  
  47.                 await self.ws_session.send_text('ssh closed')  
  48.                 return  
  49.             if not self.ws_session.status:  
  50.                 return  
  51.             await asyncio.sleep(0.01)  
  52.             if self.chanel_session.recv_ready():  
  53.                 message = self.chanel_session.recv(2048).decode('utf-8')  
  54.                 # print('<---------message----------', message)  
  55.                 if not len(message):  
  56.                     continue  
  57.                 await self.ws_session.send_text(message)  
  58.             # print('<-------------------', "end")  
  59.     async def run(self):  
  60.         if not self.ssh_session:  
  61.             raise Exception("ssh not init!")  
  62.         await self.ready()  
  63.         await asyncio.gather(  
  64.             self.web_to_ssh(),  
  65.             self.ssh_to_web()  
  66.         ) 
  67.     def clear(self):  
  68.         try:  
  69.             self.ws_session.close()  
  70.         except Exception:  
  71.             traceback.print_stack()  
  72.         try:  
  73.             self.ssh_session.close()  
  74.         except Exception:  
  75.             traceback.print_stack() 

前端

xterm.js 完全滿足,搜索下找個看著簡單的就行。 

  1. export class Term extends React.Component {  
  2.     private terminal!: HTMLDivElement;  
  3.     private fitAddon = new FitAddon();  
  4.     componentDidMount() {  
  5.         const xterm = new Terminal();  
  6.         xterm.loadAddon(this.fitAddon);  
  7.         xterm.loadAddon(new WebLinksAddon()); 
  8.         // using wss for https  
  9.         //         const socket = new WebSocket("ws://" + window.location.host + "/api/v1/ws");  
  10.         const socket = new WebSocket("ws://localhost:8000/webshell/");  
  11.         // socket.onclose = (event) => {  
  12.         //     this.props.onClose();  
  13.         // }  
  14.         socket.onopen = (event) => {  
  15.             xterm.loadAddon(new AttachAddon(socket));  
  16.             this.fitAddon.fit();  
  17.             xterm.focus();  
  18.         }  
  19.         xterm.open(this.terminal);  
  20.         xterm.onResize(({ cols, rows }) => { 
  21.             socket.send("<RESIZE>" + cols + "," + rows)  
  22.         });  
  23.         window.addEventListener('resize', this.onResize);  
  24.     }  
  25.     componentWillUnmount() {  
  26.         window.removeEventListener('resize', this.onResize);  
  27.     }  
  28.     onResize = () => {  
  29.         this.fitAddon.fit();  
  30.     }  
  31.     render() {  
  32.         return <div className="Terminal" ref={(ref) => this.terminal = ref as HTMLDivElement}></div> 
  33.     }  
  34.  

 

責任編輯:龐桂玉 來源: 馬哥Linux運維
相關推薦

2014-12-16 10:28:49

2021-03-25 08:29:33

SpringBootWebSocket即時消息

2023-08-14 08:01:12

websocket8g用戶

2017-07-11 13:58:10

WebSocket

2022-06-28 08:37:07

分布式服務器WebSocket

2016-03-14 12:33:46

2024-03-21 08:34:49

Vue3WebSocketHTTP

2023-11-17 09:35:58

2023-07-26 07:28:55

WebSocket服務器方案

2024-09-02 09:31:19

2023-12-04 07:31:41

Golangwebsocket

2010-08-09 13:37:09

FlexDjango

2021-02-26 12:37:39

WebSocketOkHttp連接

2020-08-02 08:02:26

Webshell樣本安全

2023-11-26 09:10:34

WebSocketgreeting?在線用戶

2021-03-05 11:20:24

HTTPWebshellWeb服務器

2025-01-27 12:31:23

PythonLocustWebSocket

2024-09-13 09:55:38

RustP2P網

2013-06-03 15:15:51

2024-09-11 08:35:54

點贊
收藏

51CTO技術棧公眾號

91xxx视频| 亚洲在线免费观看| 中文字幕第24页| www久久久| 午夜精品久久久久久| 天堂精品一区二区三区| 国产成人三级一区二区在线观看一| 1024日韩| 久久精品久久精品亚洲人| www.17c.com喷水少妇| 草民电影神马电影一区二区| 亚洲一区二区三区在线| 欧美一区二区三区精美影视 | 欧美一区二区精美| 日日橹狠狠爱欧美超碰| av在线导航| 久久久久高清精品| 国产精品久久久久久久小唯西川| 波多野结衣黄色| 亚洲第一网站| 九九热这里只有精品免费看| 亚洲AV无码成人精品区明星换面| 综合中文字幕| 欧美一区二区视频在线观看2020 | 国内国产精品久久| 国产精品va在线| 日韩精品成人在线| 欧美激情综合| 久久精彩免费视频| 免费网站在线高清观看| 亚洲免费成人av在线| 日韩午夜激情免费电影| 成人亚洲免费视频| 韩日精品一区| 日本大香伊一区二区三区| 你真棒插曲来救救我在线观看| 男人天堂手机在线| 中文字幕成人网| 欧洲av一区| 免费在线观看一级毛片| av一区二区三区在线| www.久久艹| www.日韩高清| 国产成人综合在线播放| 亚洲曰本av电影| 国产精品久久婷婷| 日韩精品国产欧美| 国产精品成久久久久三级| 日韩乱码在线观看| 亚洲理伦在线| 欧美一区第一页| 人人干人人干人人干| 99成人精品| 97视频在线免费观看| 日本在线观看视频网站| 亚洲大胆在线| 日本精品久久久久影院| 欧美一区二区三区网站| 久久一二三区| 日本韩国在线不卡| 日韩欧美国产另类| 美女视频一区二区| 国产又爽又黄的激情精品视频 | 亚洲日本精品| 精品美女在线观看视频在线观看| 18欧美乱大交hd1984| 中文字幕一区二区三区精彩视频 | 综合久久一区二区三区| 国产高潮呻吟久久久| caoporm免费视频在线| 亚洲精品欧美专区| 亚洲人成无码网站久久99热国产| 在线人成日本视频| 欧美视频一二三区| 亚洲日本黄色片| 中文字幕亚洲在线观看| 亚洲国产精品一区二区久| 疯狂揉花蒂控制高潮h| 国产日产精品_国产精品毛片| 一区二区三区四区视频| www.99re7| 国产精品日韩久久久| 国产精品视频一区二区三区四 | 91成人在线视频观看| 密臀av在线| 在线观看欧美黄色| 污污视频在线免费| 天堂网av成人| 久久亚洲精品毛片| 国产免费av一区| 久久99国产精品久久| 国产精品一区二区a| 九九在线视频| 一区二区视频在线| 六月丁香婷婷在线| 久久久久毛片免费观看| 亚洲精品少妇网址| 国产成人av免费在线观看| 在线欧美三区| 成人日韩av在线| 无码国产伦一区二区三区视频 | 亚洲乱码一区av黑人高潮| 长河落日免费高清观看| 精品91久久久久| 国产日韩欧美影视| 深夜福利视频在线免费观看| 中文字幕一区三区| 黄色动漫在线免费看| 久久久久久爱| 色综久久综合桃花网| 久久久午夜影院| 国产一区二区女| 日韩免费av一区二区三区| 成年网站在线视频网站| 欧美日韩中文字幕精品| 中日韩精品一区二区三区| 欧美a级片一区| 国产精品视频在线观看| 国产又爽又黄网站亚洲视频123| 中文字幕一区二区在线观看| 国产精品视频一区二区三区四区五区| 日韩第一区第二区| 色青青草原桃花久久综合| 亚洲 日本 欧美 中文幕| 成人三级伦理片| 51xx午夜影福利| 日韩成人综合网| 在线观看91久久久久久| 亚洲午夜18毛片在线看| 成人avav在线| a级黄色片免费| 国产精品久久久久久久久久辛辛| 亚洲性生活视频在线观看| 国产免费观看av| 99久久久国产精品| 久久成人免费观看| 欧美丝袜足交| 555www成人网| 欧美在线观看在线观看| 欧美理论片在线播放| 中文字幕中文字幕在线一区| 天堂在线资源视频| 国产伦精品一区二区三区视频| 97成人在线视频| 午夜av免费观看| 精品久久久一区二区| 亚洲无人区码一码二码三码| 国产一区亚洲| 国产伦精品一区二区三区视频免费 | 成人台湾亚洲精品一区二区| 色综合久综合久久综合久鬼88| 99热这里是精品| 亚洲精品ww久久久久久p站| 宇都宫紫苑在线播放| 综合日韩在线| 国产精品三区四区| 涩涩视频在线播放| 亚洲欧美中文另类| 久久riav| 风流老熟女一区二区三区| 亚洲一区二区中文在线| av免费观看不卡| 亚洲视频1区| 女女同性女同一区二区三区91| 卡通欧美亚洲| 日韩在线欧美在线国产在线| 精品二区在线观看| 偷拍与自拍一区| 99久久久无码国产精品衣服| 久久爱www久久做| 国产欧美123| 欧美a一欧美| 国产精品高精视频免费| 成人免费在线| 日韩福利在线播放| 正在播放亚洲精品| 一区二区不卡在线播放| 一级做a爰片毛片| 免费亚洲电影在线| 国产精品久久国产| 国产成人短视频在线观看| 国产在线高清精品| 阿v视频在线观看| 一区二区三区视频观看| 国产黄色小视频在线观看| 欧美日韩国产页| 中文字幕电影av| www久久久久| 香蕉视频色在线观看| 亚洲久久成人| 中文一区一区三区免费| 精品久久对白| 国产精品中文在线| 久草免费在线视频| 北条麻妃久久精品| 日本韩国一区| 欧美一卡二卡在线观看| 影音先锋在线国产| 一区二区三区在线视频免费观看 | 亚洲欧洲三级电影| 日本一区二区在线免费观看| 久久精品国产秦先生| 激情伊人五月天| 亚洲一区 二区 三区| 欧洲亚洲一区二区三区四区五区| 欧美在线在线| 国产精品自拍视频| 天堂а√在线最新版中文在线| 久久综合伊人77777蜜臀| 秋霞av在线| 精品免费日韩av| 91精品视频免费在线观看| 狠狠综合久久av一区二区小说| 欧美日韩午夜视频| 国产日韩精品一区| 中文字幕5566| 成人综合在线视频| 国产欧美精品一二三| 日韩精彩视频在线观看| 国产午夜福利视频在线观看| 在线成人亚洲| 免费看欧美黑人毛片| 亚洲成人免费| 在线看视频不卡| 欧美日韩高清| 青青成人在线| 中国av一区| 久久免费99精品久久久久久| h视频久久久| 99re国产在线播放| 国产激情精品一区二区三区| 国产精品亚洲网站| 亚洲精品国产嫩草在线观看| 清纯唯美亚洲激情| 竹内纱里奈兽皇系列在线观看| 久久免费在线观看| 成人在线免费观看黄色| 欧美黑人xxxⅹ高潮交| 超碰在线观看免费| 两个人的视频www国产精品| 淫片在线观看| 日韩视频一区在线| 成人在线网址| 欧美精品在线播放| 中文字幕在线观看网站| 久久91亚洲精品中文字幕| 最近中文字幕免费mv2018在线 | 九九热视频精品| 一区二区三区在线视频播放| 黄页网站免费观看| 亚洲成人动漫精品| 五月婷婷开心网| 亚欧色一区w666天堂| 日本道在线观看| 日本韩国欧美国产| 中文字幕在线播放不卡| 欧美日韩国产不卡| 国产三级三级在线观看| 日韩手机在线导航| 人妻与黑人一区二区三区| 亚洲国产日韩欧美综合久久| 亚洲欧洲成人在线| 亚洲人在线视频| 午夜在线观看视频| 欧美人在线观看| 国产污视频在线播放| 日本一区二区在线免费播放| av免费在线一区| 91精品一区二区| av毛片精品| 日本精品二区| 91精品综合| 国产无限制自拍| 日韩和欧美一区二区| 91福利免费观看| 成人综合在线观看| 在线国产视频一区| 玉足女爽爽91| 中文字幕在线欧美| 91精品国产综合久久久久久久久久| 精品人妻伦一区二区三区久久| 亚洲国产精品久久久久久| 欧美zozo| 九九久久久久99精品| 在线观看特色大片免费视频| 国产精品入口免费视| 99精品在免费线中文字幕网站一区 | 欧美在线一卡| 精品中文字幕在线2019| 中文字幕乱码中文乱码51精品 | 亚洲丝袜美腿一区| 欧洲美女和动交zoz0z| 国产精品久久久久毛片大屁完整版 | 九色porny丨首页入口在线| 国产美女精品视频| 欧美一级二级三级视频| 中文字幕一区二区三区有限公司| 亚洲乱码视频| 人人爽人人爽av| 久久精品网站免费观看| 精品少妇久久久| 欧美在线看片a免费观看| 丰满人妻一区二区| 亚洲性夜色噜噜噜7777| 丰乳肥臀在线| 91欧美激情另类亚洲| 久久99影视| 久久精品国产sm调教网站演员| 美女脱光内衣内裤视频久久影院| 欧美高清性xxxx| 夜色激情一区二区| 一区二区三区精| 亚洲天堂av电影| 国产传媒在线观看| 1卡2卡3卡精品视频| 日韩欧美一区二区三区免费看| 各处沟厕大尺度偷拍女厕嘘嘘 | 亚洲黄色免费视频| 午夜精品久久久久久不卡8050| 国产av无码专区亚洲a∨毛片| 色综合影院在线| 91国内外精品自在线播放| 久久综合九色综合久99| 国内综合精品午夜久久资源| 手机免费看av网站| 日韩一区有码在线| 影音先锋国产在线| 国产一区二区美女视频| 综合另类专区| 久久综合狠狠综合久久综青草| 国产精品草草| 亚洲av熟女高潮一区二区| 一区二区三区高清在线| 国产成人精品一区二三区四区五区| 最近2019中文免费高清视频观看www99| 在线天堂新版最新版在线8| 国产亚洲欧美一区二区| 亚洲日本黄色| 色天使在线视频| 欧美午夜精品久久久久久久| 亚洲区小说区图片区| 97精品在线视频| 思热99re视热频这里只精品| 99精品在线免费视频| 91玉足脚交白嫩脚丫在线播放| 日本特黄特色aaa大片免费| 精品av久久707| 国产白浆在线免费观看| 免费看成人片| 日本大胆欧美人术艺术动态| 欧美黄色激情视频| 欧美日韩综合在线| gogogogo高清视频在线| 国产91免费视频| 亚洲精品日本| 久久精品国产亚洲av久| 在线观看免费亚洲| 国产视频一区二区| 国产精品久久久久久久久久久久冷 | 国产精品欧美精品| 91麻豆成人精品国产免费网站| 另类少妇人与禽zozz0性伦| 欧美精品三级在线| 日韩网站在线免费观看| 久久天堂av综合合色蜜桃网| 国语对白做受69按摩| 久久精品久久久久电影| 国产精品sss在线观看av| 丝袜老师办公室里做好紧好爽| 国产婷婷色一区二区三区在线| 国产一级精品毛片| 久久国产色av| 亚洲区小说区图片区qvod| 久久精品免费网站| 亚洲精品大片www| 神马久久久久| 91久久夜色精品国产网站| 亚洲视屏一区| 我不卡一区二区| 日韩一区二区免费在线观看| 吉吉日韩欧美| 欧美日韩一区二区三区电影| zzijzzij亚洲日本少妇熟睡| 中文字幕一区二区在线视频| 欧美猛男性生活免费| 久久99蜜桃| 日韩精品xxx| 日本韩国欧美在线| 日本h片在线观看| 日韩国产高清一区| 成人午夜在线播放| 免费看av在线| 久久久久久久久久婷婷| 日韩电影一区| 亚洲最大免费视频| 欧美一区二区三区啪啪| 92国产精品| 国产一区 在线播放| 亚洲国产激情av| 午夜一区在线观看|