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

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內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: