Vue+websocket+django实现WebSSH demo
效果:
如下图,实现了webssh,可以通过web方式,进行实时命令处理
注意:Django 3.0不支持dwebsocket模块,启动时,会报错:
TypeError: WebSocketMiddleware() takes no arguments因此,如果使用Django 3.0,必须使用channels
前端:
包依赖:"xterm": "^4.14.1", "xterm-addon-fit": "^0.5.0"
封装SSH组件:/components/SSH/index.vue
<template>
<div ref="xterm" class="terminal" :style="styleVar" />
</template>
<script>
import 'xterm/css/xterm.css'
import { Terminal } from 'xterm'
import { FitAddon } from 'xterm-addon-fit'
export default {
name: 'xterm',
props: {
ip: { type: String }, // 通过父组件传递登录ip
height: {
type: Number, // xterm显示屏幕,高度
default: 100,
},
},
data() {
return {
term: null,
socket: null,
}
},
computed: { // 动态设置xterm显示屏幕高度
styleVar() {
return {
'--terminal-height': this.height + "vh"
}
}
},
mounted() { // 初始化链接
this.init()
this.initSocket()
},
beforeDestroy() { // 退出销毁链接
this.socket.close()
this.term.dispose()
},
methods: {
init() { // 初始化Terminal
this.term = new Terminal({
fontSize: 18,
convertEol: true, // 启用时,光标将设置为下一行的开头
rendererType: 'canvas', // 渲染类型
cursorBlink: true, // 光标闪烁
cursorStyle: 'bar', // 光标样式 underline
theme: {
background: '#060101', // 背景色
cursor: 'help' // 设置光标
}
})
},
initSocket() { // 初始化Websocket
const fitPlugin = new FitAddon()
this.term.loadAddon(fitPlugin)
const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'
this.socket = new WebSocket(`${protocol}//${window.location.host}/socket/ws/ssh/${this.ip}`)
this.socket.onmessage = e => {
const reader = new window.FileReader()
reader.onload = () => this.term.write(reader.result)
reader.readAsText(e.data, 'utf-8')
}
this.socket.onopen = () => {
this.term.open(this.$refs.xterm)
this.term.focus()
fitPlugin.fit()
}
this.socket.onclose = e => {
if (e.code === 1234) { // 结束标记
window.location.href = 'about:blank'
window.close()
} else {
setTimeout(() => this.term.write('\r\nConnection is closed.\r\n'), 200)
}
}
this.term.onData(data => this.socket.send(JSON.stringify({ data })))
this.term.onResize(({ cols, rows }) => {
this.socket.send(JSON.stringify({ resize: [cols, rows] }))
})
window.onresize = () => fitPlugin.fit()
}
}
}
</script>
<style lang="scss" scoped>
.terminal {
display: flex;
width: 100%;
min-height: var(--terminal-height);
flex: 1;
background-color: #000;
}
.terminal > div {
flex: 1;
}
</style> 父组件引用:
后台:
Django==3.1.10 daphne==3.0.2 paramiko==2.8.0 channels==3.0.4
假定目录结构如下:
(1) 修改asgi.py
Tutorial Part 1: Basic Setup — Channels 3.0.4 documentation
(2) 修改settings.py
信道中间层用redis 可参加 https://channels.readthedocs.io/en/stable/topics/channel_layers.html
(3)配置路由
settings.py
routing.py
consumers.py
Nginx配置:
扩展
如果使用的是状态框,可参考下面内容
Last updated