如何安全地使用WebSocket(1)
如同其它通信协议一样,WebSocket并不会处理授权或认证,所以如何安全地使用它就是我们要考虑的事情了。
为方便修改,我们把websocket_server 包复制到本地(python会优先读取位于项目目录下的包),修改server.py:
# 头部引入logging import logging # 创建服务端时定义 server = WebsocketServer(9001, host='0.0.0.0',loglevel=logging.INFO) # 防止空参数报错 def client_left(client, server): try: print("Client(%d) disconnected" % client['id']) except Exception: return
客户端在发起通信初期会发送一个基于HTTP协议的握手,服务端通过报文内容确认这是一个WebSocket请求后,也会回复一个表示支持WebSocket并接受请求的报文,完成握手。
握手报文的详细内容就不说了,这些协议都会帮我们自动处理。
在此阶段,报文中有一个可以自定义的表项:”Sec-WebSocket-Protocol”子协议,一般用于区分同一WebSocket服务端下的不同项目。不过说到底,他就是一个字段,我们就用Sec-WebSocket-Protocol来验证客户端身份吧:
//在创建时带上第二个参数即可定义该表项: ws = new WebSocket("ws:server-addr",'nvshen')
设置后尝试连接,报:
WebSocket connection to 'ws://gouzi.live:9001/' failed: Error during WebSocket handshake: Sent non-empty 'Sec-WebSocket-Protocol' header but no response was received
看下报错内容:设置了一个非空的Sec-WebSocket-Protocol,但是没有回复。哦,我已经表明我是女神了,你居然没点反应!不聊了!!!
好吧,看来我们的客户端妹子还真有点脾气,那我们在服务端给我们的女神一个回复吧:
server.py:
#给websocket_server定义一个名叫protocol的属性,也就是后面用来验证的字符串了 WebsocketServer.protocol='nvshen' #建议加密字段或改为验证token
#md5加密: from hashlib import md5 protocol='nvshen' WebsocketServer.protocol = md5(protocol.encode('utf-8')).hexdigest()
websocket_server.py
# Line:331 def handshake(self): headers = self.read_http_headers() # 检验sec-websocket-protocol try: #注意大小写 assert headers['sec-websocket-protocol'].lower() == WebsocketServer.protocol except AssertionError: logger.info("不是我妹子的电话,不接!") self.keep_alive = False return # 通过验证后,回复报文(需要与接收一至): def make_handshake_response(cls, key): return \ 'HTTP/1.1 101 Switching Protocols\r\n'\ 'Upgrade: websocket\r\n' \ 'Connection: Upgrade\r\n' \ 'Sec-WebSocket-Protocol: '+WebsocketServer.protocol+'\r\n'\ 'Sec-WebSocket-Accept: %s\r\n' \ '\r\n' % cls.calculate_response_key(key)
如果不是女神,直接不聊!耿直Boy+1 👏👏👏
*有兴趣的了解WebSocket协议的,可以看看知乎上的大神是怎么秀的: