CHANNEL_LAYERS = {
'default': {
'BACKEND': 'channels_redis.core.RedisChannelLayer',
'CONFIG': {
"hosts": [('ops-coffee.cn', 6379)],
},
},
}
然后将处理WebSSH连接名为SSHConsumer的Consumer做改造,以使其支持layer,代码如下
class SSHConsumer(WebsocketConsumer):
def connect(self):
格式化参数
ssh_connect_args = args(self.scope)
新建录像记录
self.host = Host.objects.get(host=ssh_connect_args.get('host'))
self.group_name = '%s-%s-%d' % (
ssh_connect_args.get('host'), ssh_connect_args.get('username'), time.time())
self.therecord = Record.objects.create(
host=self.host,
user=self.scope['user'],
group=self.group_name,
channel=self.channel_name,
cols=ssh_connect_args.get('cols'),
rows=ssh_connect_args.get('rows'),
is_connecting=True
)
async_to_sync(self.channel_layer.group_add)(
self.group_name,
self.channel_name
)
self.accept()
WebSocket连接成功后,连接ssh
self.ssh = SSHBridge(self.therecord, websocket=self)
self.ssh.connect(**ssh_connect_args)
def disconnect(self, close_code):
将连接状态置为False
self.therecord.is_connecting = False
self.therecord.save()
async_to_sync(self.channel_layer.group_discard)(
self.group_name,
self.channel_name
)
self.ssh.close()
def receive(self, text_data=None):
text_data = json.loads(text_data)
if text_data.get('flag') == 'resize':
self.ssh.resize_pty(cols=text_data['cols'], rows=text_data['rows'])
else:
self.ssh.shell(data=text_data.get('data', ''))
def ssh_message(self, event):
self.send(text_data=json.dumps(
event['message']
))
在connect连接建立时新建一条记录,存储主机、用户、group_name、channel_name以及初始窗口的cols、rows信息,同时标记is_connecting为True,这里的group_name命名与文章『堡垒机的核心武器:WebSSH录像实现』中我们定义的录像文件名规则一致,另外将这篇文章中新建录像记录的操作从SSHBridge.record中给转到了连接建立的connect中来,更合理也更方便
在disconnect连接关闭时,将is_connecting标记为False,这样我们在前端页面上就可以根据这个标记来判断WebSSH是否正在连接,如果连接则展示监控和强制结束按钮,否则展示播放和命令提取按钮
同时添加个ssh_message方法,用来接收发送到组的数据
到这里,我们已经将WebSSH改造成了支持layer的模式,那么接下来就是要在用户点击监控的时候将用户与服务端建立的连接channel加入到上述group中
新建一个名为MonitorConsumer的consumer,主要用来处理监控连接
class MonitorConsumer(WebsocketConsumer):
def connect(self):
pk = self.scope['url_route']['kwargs'].get('id')
self.group_name = Record.objects.get(id=pk).group
async_to_sync(self.channel_layer.group_add)(
self.group_name,
self.channel_name
)
self.accept()
判断用户已经结束了这个webssh连接时就关闭监控
self.connecting = Record.objects.get(id=pk).is_connecting
if not self.connecting:
self.close()
def disconnect(self, close_code):
async_to_sync(self.channel_layer.group_discard)(
self.group_name,
self.channel_name
)
self.close()
def receive(self, text_data=None):
pass
def ssh_message(self, event):
self.send(text_data=json.dumps(
event['message']
))
MonitorConsumer与SSHConsumer有两个地方不一样,其一是SSHConsumer中我们直接新生成了个group_name,而MonitorConsumer中需要在connect时获取到要监控的ID,然后通过ID拿到group_name,将monitor连接加入到这个group,其二是监控只能看,不能操作,所以也不需要前端发送数据的term.on和Consumer的receive处理数据
最后需要修改SSHBridge方法中发送给websocket的指令,从self.websocket.send改为发送到group的模式,如下
自学几个月前端,为什么感觉什么都没学到??
这种现象在很多的初学者和自学前端的同学中是比较的常见的。
因为自学走的弯路是比较的多的,会踩很多的坑,学习的过程中是比较的迷茫的。
最重要的是,在学习的过程中,不知道每个部分该学哪些知识点,学到什么程度才算好,学了能做什么。
很多自学的朋友往往都是自己去找资料学习的,资料上有的或许就学到了,资料上没有的或许就没有学到。
这就会给人一个错误的信息就是,我把资料上的学完了,估计也-就差不多的了。
但是真的是这样的吗?非也,因为很多人找的资料就是很基础的。学完了也就是掌握一点基础的东西。分享给你一份前端分析路线,你可以参考。
还有很多的同学在学习的过程中一味的追求学的速度,很快速的刷视频,写了后面忘了前面,最后什么都没有学到,什么都知道,但是什么都不懂,要具体说,也说不出个所以然。
所以学习编程一定要注重实践操作,练习敲代码的时间一定要多余看视频的时间。 开源分享:docs.qq.com/doc/DSmRnRG…