From 9ab2862682848567eb867559e782ab5141ab7aca Mon Sep 17 00:00:00 2001 From: Stepan Henek Date: Mon, 13 Feb 2017 13:34:08 +0100 Subject: [PATCH 1/3] Inherit everything from object. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * this will aviod the python2/python3 incosistency (using "new" class style for all implementations) * fixes super() fails with error: TypeError “argument 1 must be type, not classobj” exception when overriding class methods see http://stackoverflow.com/questions/1713038/super-fails-with-error-typeerror-argument-1-must-be-type-not-classobj --- websocket_server/websocket_server.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/websocket_server/websocket_server.py b/websocket_server/websocket_server.py index dd0af82..44be5b0 100644 --- a/websocket_server/websocket_server.py +++ b/websocket_server/websocket_server.py @@ -49,7 +49,7 @@ # -------------------------------- API --------------------------------- -class API(): +class API(object): def run_forever(self): try: @@ -160,7 +160,7 @@ def handler_to_client(self, handler): return client -class WebSocketHandler(StreamRequestHandler): +class WebSocketHandler(StreamRequestHandler, object): def __init__(self, socket, addr, server): self.server = server From 797119715068774c987e0051537c890d97ae5f79 Mon Sep 17 00:00:00 2001 From: Stepan Henek Date: Tue, 21 Mar 2017 11:41:08 +0100 Subject: [PATCH 2/3] Inject autentication into handshake. --- websocket_server/websocket_server.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/websocket_server/websocket_server.py b/websocket_server/websocket_server.py index 44be5b0..f8d8097 100644 --- a/websocket_server/websocket_server.py +++ b/websocket_server/websocket_server.py @@ -71,6 +71,9 @@ def client_left(self, client, server): def message_received(self, client, server, message): pass + def authenticate(self, msg): + return True + def set_fn_new_client(self, fn): self.new_client = fn @@ -80,6 +83,9 @@ def set_fn_client_left(self, fn): def set_fn_message_received(self, fn): self.message_received = fn + def set_fn_authenticate(self, fn): + self.authenticate = fn + def send_message(self, client, msg): self._unicast_(client, msg) @@ -147,6 +153,9 @@ def _client_left_(self, handler): if client in self.clients: self.clients.remove(client) + def _authenticate_(self, msg): + return self.authenticate(msg) + def _unicast_(self, to_client, msg): to_client['handler'].send_message(msg) @@ -303,6 +312,11 @@ def handshake(self): logger.warning("Client tried to connect but was missing a key") self.keep_alive = False return + if not self.server._authenticate_(message): + logger.warning("Failed to authenticate a client.") + self.request.send(self.make_unauthorized_response().encode()) + self.keep_alive = False + return response = self.make_handshake_response(key) self.handshake_done = self.request.send(response.encode()) self.valid_client = True @@ -316,6 +330,9 @@ def make_handshake_response(self, key): 'Sec-WebSocket-Accept: %s\r\n' \ '\r\n' % self.calculate_response_key(key) + def make_unauthorized_response(self): + return 'HTTP/1.1 403 Forbidden\r\n\r\n' + def calculate_response_key(self, key): GUID = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11' hash = sha1(key.encode() + GUID.encode()) From ed0c4bb327b4c710fca9e25ad27d201190366e3f Mon Sep 17 00:00:00 2001 From: Stepan Henek Date: Tue, 21 Mar 2017 11:51:15 +0100 Subject: [PATCH 3/3] Mention authentication method in README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 22d4b9b..c0bbb3d 100644 --- a/README.md +++ b/README.md @@ -64,6 +64,7 @@ The WebsocketServer can be initialized with the below parameters. | `set_fn_new_client()` | Sets a callback function that will be called for every new `client` connecting to us | function | None | | `set_fn_client_left()` | Sets a callback function that will be called for every `client` disconnecting from us | function | None | | `set_fn_message_received()` | Sets a callback function that will be called when a `client` sends a message | function | None | +| `set_fn_authenticate()` | Sets a callback function that will be called during the handshake | function | None | | `send_message()` | Sends a `message` to a specific `client`. The message is a simple string. | client, message | None | | `send_message_to_all()` | Sends a `message` to **all** connected clients. The message is a simple string. | message | None | @@ -75,6 +76,7 @@ The WebsocketServer can be initialized with the below parameters. | `set_fn_new_client()` | Called for every new `client` connecting to us | client, server | | `set_fn_client_left()` | Called for every `client` disconnecting from us | client, server | | `set_fn_message_received()` | Called when a `client` sends a `message` | client, server, message | +| `set_fn_authenticate()` | Called every time when a handshake is triggered | message | The client passed to the callback is the client that left, sent the message, etc. The server might not have any use to use. However it is passed in case you want to send messages to clients.