1. 程式人生 > >基於 django 實現的 webssh 簡單例子

基於 django 實現的 webssh 簡單例子

exce attr index tar sum thread 命名 ssh 項目

技術分享圖片

說明

新建一個 django 程序,本文為 chain。

以下僅為簡單例子,實際應用 可根據自己平臺情況 進行修改。

打開首頁後,需要輸入1,後臺去登錄主機,然後返回登錄結果。

正常項目 可以post 主機和登錄賬戶,進行權限判斷,然後去後臺讀取賬戶密碼,進行登錄。

djang後臺

需要安裝以下模塊

安裝後會有一個版本號報錯,不影響

channels==2.0.2
channels-redis==2.1.0
amqp==1.4.9
anyjson==0.3.3
asgi-redis==1.4.3
asgiref==2.3.0
async-timeout==2.0.0
attrs==17.4.0

cd /tmp/
wget https://files.pythonhosted.org/packages/12/2a/e9e4fb2e6b2f7a75577e0614926819a472934b0b85f205ba5d5d2add54d0/Twisted-18.4.0.tar.bz2
tar xf Twisted-18.4.0.tar.bz2
cd Twisted-18.4.0
python3 setup.py install

啟動redis


目錄

chain/
        chain/
             settings.py
             asgi.py
             consumers.py
             routing.py
    templates/
           index.html

settings.py

# django-channels配置
CHANNEL_LAYERS = {
    "default": {
        "BACKEND": "channels_redis.core.RedisChannelLayer",
        "CONFIG": {
            "hosts": [("127.0.0.1", 6379)],
        },
    },
}

# 配置ASGI
ASGI_APPLICATION = "chain.routing.application"

consumers.py

from asgiref.sync import async_to_sync
from channels.generic.websocket import WebsocketConsumer

import paramiko
import threading
import time

from channels.layers import get_channel_layer
channel_layer = get_channel_layer()

class MyThread(threading.Thread):
    def __init__(self, id, chan):
        threading.Thread.__init__(self)
        self.chan = chan

    def run(self):
        while not self.chan.chan.exit_status_ready():
            time.sleep(0.1)
            try:
                data = self.chan.chan.recv(1024)
                async_to_sync(self.chan.channel_layer.group_send)(
                    self.chan.scope[‘user‘].username,
                    {
                        "type": "user.message",
                        "text": bytes.decode(data)
                    },
                )
            except Exception as ex:
                print(str(ex))
        self.chan.sshclient.close()
        return False

class EchoConsumer(WebsocketConsumer):

    def connect(self):
        # 創建channels group, 命名為:用戶名,並使用channel_layer寫入到redis
        async_to_sync(self.channel_layer.group_add)(self.scope[‘user‘].username, self.channel_name)
        # 返回給receive方法處理
        self.accept()

    def receive(self, text_data):

        if text_data == ‘1‘:
            self.sshclient = paramiko.SSHClient()
            self.sshclient.load_system_host_keys()
            self.sshclient.set_missing_host_key_policy(paramiko.AutoAddPolicy())
            self.sshclient.connect(‘47.104.140.38‘, 22, ‘root‘, ‘123456‘)
            self.chan = self.sshclient.invoke_shell(term=‘xterm‘)
            self.chan.settimeout(0)
            t1 = MyThread(999, self)
            t1.setDaemon(True)
            t1.start()
        else:
            try:
                self.chan.send(text_data)
            except Exception as ex:
                print(str(ex))

    def user_message(self, event):
        # 消費
        self.send(text_data=event["text"])

    def disconnect(self, close_code):
        async_to_sync(self.channel_layer.group_discard)(self.scope[‘user‘].username, self.channel_name)

asgi.py

import os
import django
from channels.routing import get_default_application

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "chain.settings")
django.setup()
application = get_default_application()

routing.py

from channels.auth import AuthMiddlewareStack
from channels.routing import URLRouter, ProtocolTypeRouter
from django.urls import path

from .consumers import EchoConsumer

application = ProtocolTypeRouter({
    "websocket": AuthMiddlewareStack(
        URLRouter([
            path(r"ws/", EchoConsumer),
            # path(r"stats/", StatsConsumer),
        ])
    )
})

網頁設置:

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>django webssh 例子</title>

    <link href="/static/css/plugins/ztree/awesomeStyle/awesome.css" rel="stylesheet">

    <link href="/static/webssh_static/css/xterm.min.css" rel="stylesheet" type="text/css"/>
    <style>
        body {
            padding-bottom: 30px;
        }

        .terminal {
            border: #000 solid 5px;
            font-family: cursive;
        {#                font-family: Arial, Helvetica, Tahoma ,"Monaco", "DejaVu Sans Mono", "Liberation Mono", sans-serif;#}{#                font-family: Tahoma, Helvetica, Arial, sans-serif;#}{#                font-family: "\5B8B\4F53","","Monaco", "DejaVu Sans Mono", "Liberation Mono", "Microsoft YaHei", monospace;#} font-size: 15px;
        {#                color: #f0f0f0;#} background: #000;
        {#                width: 893px;#}{#                height: 550px;#} box-shadow: rgba(0, 0, 0, 0.8) 2px 2px 20px;
        }

        .reverse-video {
            color: #000;
            background: #f0f0f0;
        }
    </style>
</head>
<body>

<div id="terms"></div>
</body>

<script src="/static/webssh_static/js/xterm.min.js"></script>
<script>
    var socket = new WebSocket(‘ws://‘ + window.location.host + ‘/ws/‘);

    socket.onopen = function () {

        var term = new Terminal();
        term.open(document.getElementById(‘terms‘));

        term.on(‘data‘, function (data) {
            console.log(data);
            socket.send(data);
        });

        socket.onmessage = function (msg) {
            console.log(msg);
            console.log(msg.data);
            term.write(msg.data);
        };
        socket.onerror = function (e) {
            console.log(e);
        };

        socket.onclose = function (e) {
            console.log(e);
            term.destroy();
        };
    };

</script>

</html>

基於 django 實現的 webssh 簡單例子