I am writing a small app where I use Tornado websockets. I use cookies for authentication, and I therefore want to check this when establishing the web socket.
So here is the challenge (building on the official websockets example):
class EchoWebSocket(tornado.websocket.WebSocketHandler):
def open(self):
userx = self.get_secure_cookie("user")
if not userx:
self.send_error(403) #I want to redirect or otherwise stop the user
print "WebSocket opened"
def on_message(self, message):
userx = self.get_secure_cookie("user")
self.write_message(u"%s said: %s" % (userx, message))
def on_close(self):
print "WebSocket closed"
Turns out that this is not very popular with Tornado, throwing this error:
ERROR:root:Exception in callback <tornado.stack_context._StackContextWrapper object at 0x10fa10db8>
Traceback (most recent call last):
....
File "/Library/Python/2.7/site-packages/tornado-2.4-py2.7.egg/tornado/iostream.py", line 565, in _check_closed
raise IOError("Stream is closed")
IOError: Stream is closed
Is it even possible to “authenticate or cancel” during websockets handshake? Is this a problem with my code, or is there a issue/missing feature with Tornado? Is Tornado capable of sending some error condition over websockets to trigger the onerror handler at the client side in this situation (can not find any way to force an error condition in the manual)?
The sequence of events I am trying to achieve is:
-
the user logs in using regular web requests, and a session token is stored as a secure cookie
-
the user loads a page that uses websockets, javascript attempts to establish the socket
-
before the socket is established I want to check the presence of a valid session token
- if valid token, the socket is established and my app works as intended
- if invalid token, there is no socket, and the user gets an error (alternatively, an websocket error condition is raised by the server)
You can track your users, you can do it easily, as each user connects to the server is created an instance, check this SO link.
Regarding that you want to close the connection if he is not authenticated, you a can do it by calling close() method inside WebSWebSocketHandler instance like this:
Check this in Tornado:
tornado.websocket.WebSocketHandler.WebSocketHandler.close()I didn’t try it by myself. You can try it and tell me if it works for you.