##// END OF EJS Templates
authenticate Websockets with the session cookie...
MinRK -
Show More
@@ -16,6 +16,9 b' Authors:'
16 # Imports
16 # Imports
17 #-----------------------------------------------------------------------------
17 #-----------------------------------------------------------------------------
18
18
19 import logging
20 import Cookie
21
19 from tornado import web
22 from tornado import web
20 from tornado import websocket
23 from tornado import websocket
21
24
@@ -165,20 +168,58 b' class ZMQStreamHandler(websocket.WebSocketHandler):'
165 else:
168 else:
166 self.write_message(msg)
169 self.write_message(msg)
167
170
168
171 class AuthenticatedZMQStreamHandler(ZMQStreamHandler):
169 class IOPubHandler(ZMQStreamHandler):
172 def open(self, kernel_id):
173 self.kernel_id = kernel_id
174 self.session = Session()
175 self.save_on_message = self.on_message
176 self.on_message = self.on_first_message
177
178 def get_current_user(self):
179 password = self.get_secure_cookie("password")
180 if password is None:
181 # clear cookies, to prevent future Invalid cookie signature warnings
182 self._cookies = Cookie.SimpleCookie()
183 if self.application.password and self.application.password != password:
184 return None
185 return self.get_secure_cookie("user") or 'anonymous'
186
187 def _inject_cookie_message(self, msg):
188 """Inject the first message, which is the document cookie,
189 for authentication."""
190 if isinstance(msg, unicode):
191 # Cookie can't constructor doesn't accept unicode strings for some reason
192 msg = msg.encode('utf8', 'replace')
193 try:
194 self._cookies = Cookie.SimpleCookie(msg)
195 except:
196 logging.warn("couldn't parse cookie string: %s",msg, exc_info=True)
197
198 def on_first_message(self, msg):
199 self._inject_cookie_message(msg)
200 if self.get_current_user() is None:
201 logging.warn("Couldn't authenticate WebSocket connection")
202 raise web.HTTPError(403)
203 self.on_message = self.save_on_message
204
205
206 class IOPubHandler(AuthenticatedZMQStreamHandler):
170
207
171 def initialize(self, *args, **kwargs):
208 def initialize(self, *args, **kwargs):
172 self._kernel_alive = True
209 self._kernel_alive = True
173 self._beating = False
210 self._beating = False
174 self.iopub_stream = None
211 self.iopub_stream = None
175 self.hb_stream = None
212 self.hb_stream = None
176
213
177 def open(self, kernel_id):
214 def on_first_message(self, msg):
215 try:
216 super(IOPubHandler, self).on_first_message(msg)
217 except web.HTTPError:
218 self.close()
219 return
178 km = self.application.kernel_manager
220 km = self.application.kernel_manager
179 self.kernel_id = kernel_id
180 self.session = Session()
181 self.time_to_dead = km.time_to_dead
221 self.time_to_dead = km.time_to_dead
222 kernel_id = self.kernel_id
182 try:
223 try:
183 self.iopub_stream = km.create_iopub_stream(kernel_id)
224 self.iopub_stream = km.create_iopub_stream(kernel_id)
184 self.hb_stream = km.create_hb_stream(kernel_id)
225 self.hb_stream = km.create_hb_stream(kernel_id)
@@ -187,9 +228,13 b' class IOPubHandler(ZMQStreamHandler):'
187 # close the connection.
228 # close the connection.
188 if not self.stream.closed():
229 if not self.stream.closed():
189 self.stream.close()
230 self.stream.close()
231 self.close()
190 else:
232 else:
191 self.iopub_stream.on_recv(self._on_zmq_reply)
233 self.iopub_stream.on_recv(self._on_zmq_reply)
192 self.start_hb(self.kernel_died)
234 self.start_hb(self.kernel_died)
235
236 def on_message(self, msg):
237 pass
193
238
194 def on_close(self):
239 def on_close(self):
195 # This method can be called twice, once by self.kernel_died and once
240 # This method can be called twice, once by self.kernel_died and once
@@ -245,15 +290,20 b' class IOPubHandler(ZMQStreamHandler):'
245 self.on_close()
290 self.on_close()
246
291
247
292
248 class ShellHandler(ZMQStreamHandler):
293 class ShellHandler(AuthenticatedZMQStreamHandler):
249
294
250 def initialize(self, *args, **kwargs):
295 def initialize(self, *args, **kwargs):
251 self.shell_stream = None
296 self.shell_stream = None
252
297
253 def open(self, kernel_id):
298 def on_first_message(self, msg):
299 try:
300 super(ShellHandler, self).on_first_message(msg)
301 except web.HTTPError:
302 self.close()
303 return
254 km = self.application.kernel_manager
304 km = self.application.kernel_manager
255 self.max_msg_size = km.max_msg_size
305 self.max_msg_size = km.max_msg_size
256 self.kernel_id = kernel_id
306 kernel_id = self.kernel_id
257 try:
307 try:
258 self.shell_stream = km.create_shell_stream(kernel_id)
308 self.shell_stream = km.create_shell_stream(kernel_id)
259 except web.HTTPError:
309 except web.HTTPError:
@@ -261,8 +311,8 b' class ShellHandler(ZMQStreamHandler):'
261 # close the connection.
311 # close the connection.
262 if not self.stream.closed():
312 if not self.stream.closed():
263 self.stream.close()
313 self.stream.close()
314 self.close()
264 else:
315 else:
265 self.session = Session()
266 self.shell_stream.on_recv(self._on_zmq_reply)
316 self.shell_stream.on_recv(self._on_zmq_reply)
267
317
268 def on_message(self, msg):
318 def on_message(self, msg):
@@ -91,6 +91,12 b' var IPython = (function (IPython) {'
91 console.log("Starting WS:", ws_url);
91 console.log("Starting WS:", ws_url);
92 this.shell_channel = new this.WebSocket(ws_url + "/shell");
92 this.shell_channel = new this.WebSocket(ws_url + "/shell");
93 this.iopub_channel = new this.WebSocket(ws_url + "/iopub");
93 this.iopub_channel = new this.WebSocket(ws_url + "/iopub");
94 send_cookie = function(){
95 this.send(document.cookie);
96 console.log(this);
97 }
98 this.shell_channel.onopen = send_cookie;
99 this.iopub_channel.onopen = send_cookie;
94 };
100 };
95
101
96
102
General Comments 0
You need to be logged in to leave comments. Login now