首頁 > 軟體

Python Flask框架開發之運用SocketIO實現WebSSH方法詳解

2022-10-10 14:00:13

Flask 框架中如果想要實現WebSocket功能有許多種方式,運用SocketIO庫來實現無疑是最簡單的一種方式,Flask中封裝了一個flask_socketio庫該庫可以直接通過pip倉庫安裝,如下內容將重點簡述SocketIO庫在Flask框架中是如何被應用的,最終實現WebSSH命令列終端功能,其可用於在Web瀏覽器內實現SSH命令列執行。

首先我們先來看一下SocketIO庫是如何進行通訊的,對於前端部分需要引入socket.io這個框架,然後就是利用該框架內提供的各類函數實現建立WS通道,如下程式碼:

程式碼中通過呼叫io.connect來連線後端,socket.emit則是用於向後端推播一條訊息,而socket.on則是一個回撥函數,一旦有資料被傳出則第一時間執行回撥函數內的程式碼。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script type="text/javascript" src="https://cdn.lyshark.com/javascript/jquery/3.5.1/jquery.min.js"></script>
    <script type="text/javascript" src="https://cdn.lyshark.com/javascript/socket.io/socket.io.min.js"></script>
</head>
<body>
<script type="text/javascript" charset="UTF-8">
    $(document).ready(function() {
        namespace = '/Socket';
        var socket = io.connect("http://" + document.domain + ":" + location.port + namespace);
        // 初始化完成後,傳送一條訊息
        socket.emit("message",{"data":"hello lyshark"});
        // 收到資料後,執行輸出
        socket.on('response', function(recv) {
            console.log('hello lyshark ' + recv.Data)
        });
    });
</script>
</body>
</html>

接著就是後端,後端部分程式碼如下所示,程式碼中app.config['SECRET_KEY']是設定一個安全金鑰這裡可以隨意填寫,通過socketio = SocketIO(app)初始化一個SOCKET物件,當有訊息出現時SocketIO會自動執行相應的處理常式,常見的處理方法也就如下這三種。

  • message 出現訊息後,率先執行此處
  • connect 當websocket連線成功時,自動觸發connect預設方法
  • disconnect 當websocket連線失敗時,自動觸發disconnect預設方法
from flask import Flask,render_template,request
from flask_socketio import SocketIO
async_mode = None
app = Flask(import_name=__name__,
            static_url_path='/python',   # 設定靜態檔案的存取url字首
            static_folder='static',      # 設定靜態檔案的資料夾
            template_folder='templates') # 設定模板檔案的資料夾
app.config['SECRET_KEY'] = "lyshark"
socketio = SocketIO(app)
@app.route("/")
def index():
    return render_template("index.html")
# 出現訊息後,率先執行此處
@socketio.on("message",namespace="/Socket")
def socket(message):
    print("接收到訊息:",message['data'])
    for i in range(1,100):
        socketio.sleep(1)
        socketio.emit("response",           # 繫結通訊
                      {"Data":i},           # 返回socket資料
                      namespace="/Socket")
# 當websocket連線成功時,自動觸發connect預設方法
@socketio.on("connect",namespace="/Socket")
def connect():
    print("連結建立成功..")
# 當websocket連線失敗時,自動觸發disconnect預設方法
@socketio.on("disconnect",namespace="/Socket")
def disconnect():
    print("連結建立失敗..")
if __name__ == '__main__':
    socketio.run(app,debug=True,host="0.0.0.0")

如上就是前後端所有的程式碼,當我們執行Flask後端時,開啟前端頁面並檢視控制檯,可以看到效果,後臺會每隔一段時間自動向前端推播一個訊息此時這個通道也算是建立成功了。

原理明白了以後,再去實現一個WebSSH終端就會變得很容易,WebSSH終端我們需要xterm這個前端庫來實現,其原理就是當後臺有資料輸出或前臺有輸入時第一時間傳遞給SSH模組執行然後返回結果,我們先來看前端部分是如何實現這段功能的。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script type="text/javascript" src="https://cdn.lyshark.com/javascript/jquery/3.5.1/jquery.min.js"></script>
    <script type="text/javascript" src="https://cdn.lyshark.com/javascript/socket.io/socket.io.min.js"></script>
    <link rel="stylesheet" href="https://cdn.lyshark.com/javascript/bootstrap/3.3.7/css/bootstrap.min.css" rel="external nofollow"  />
    <link rel="stylesheet" href="https://cdn.lyshark.com/javascript/xterm/xterm.css" rel="external nofollow"  />
    <script type="text/javascript" src="https://cdn.lyshark.com/javascript/xterm/xterm.js"></script>
</head>
<body>
    <div id="terminal"></div>
    <script>
      var window_width = $(window).width();
      var window_height = $(window).height();
      var term = new Terminal(
            {
                cols: Math.floor(window_width/9),
                rows: Math.floor(window_height/20),
                useStyle:false,
                convertEol: true,
                cursorBlink:true,
                cursorStyle:null,
            });
        console.log("高度" + window_height + "寬度" + window_width);
        $(document).ready(function() {
            namespace = '/Socket';
            var socket = io.connect("http://" + document.domain + ":" + location.port + namespace);
            socket.on("connect",function(){
                term.open(document.getElementById('terminal'));
            });
            // 接受後端資料,並寫到控制檯
            socket.on("response",function(recv){
                term.write(recv.Data);
            });
            // 傳送訊息到對端
            term.on("data",function(data){
               socket.send(data);
               //socket.emit("message",{"data":data});
            });
        });
</script>
</body>
</html>

上方程式碼中當連結SOCKET成功後,則socket.on("response",function(recv)用於接收後臺的輸出,一旦後臺有輸出資料則直接呼叫term.write(recv.Data);將該資料寫出到控制檯,而term.on則是xterm中提供的接收方法,其作用是接收使用者的輸入並將該輸入傳遞給後臺來處理。

那後臺是如何處理的呢,其實後端只是使用paramiko模組建立一個SSH隧道,並在message函數內處理傳送接收資料。

from flask import Flask,render_template,request
from flask_socketio import SocketIO
import paramiko
async_mode = None
app = Flask(import_name=__name__,
            static_url_path='/python',   # 設定靜態檔案的存取url字首
            static_folder='static',      # 設定靜態檔案的資料夾
            template_folder='templates') # 設定模板檔案的資料夾
app.config['SECRET_KEY'] = "lyshark"
socketio = SocketIO(app)
def ssh_cmd():
    tran = paramiko.Transport(('192.168.150.129', 22,))
    tran.start_client()
    tran.auth_password('root', '1233')
    chan = tran.open_session()
    chan.get_pty(height=492,width=1312)
    chan.invoke_shell()
    return chan
sessions = ssh_cmd()
@app.route("/")
def index():
    return render_template("index.html")
# 出現訊息後,率先執行此處
@socketio.on("message",namespace="/Socket")
def socket(message):
    print("接收到訊息:",message)
    sessions.send(message)
    ret = sessions.recv(4096)
    socketio.emit("response", {"Data": ret.decode("utf-8")}, namespace="/Socket")
    print(message)
# 當websocket連線成功時,自動觸發connect預設方法
@socketio.on("connect",namespace="/Socket")
def connect():
    ret = sessions.recv(4096)
    socketio.emit("response", {"Data": ret.decode("utf-8")}, namespace="/Socket")
    print("連結建立成功..")
# 當websocket連線失敗時,自動觸發disconnect預設方法
@socketio.on("disconnect",namespace="/Socket")
def disconnect():
    print("連結建立失敗..")
if __name__ == '__main__':
    socketio.run(app,debug=True,host="0.0.0.0")

程式碼執行後我們存取Web頁面,即可成功登入到Linux主機,並執行任意命令。

當執行輸出目錄時也是帶有顏色的,顏色的上色部分是xterm中自帶的並不需要自己去設定。

到此這篇關於Python Flask框架開發之運用SocketIO實現WebSSH方法詳解的文章就介紹到這了,更多相關Python SocketIO實現WebSSH內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com