如何确保Tornado只打开经过身份验证的用户的websocket?

时间:2013-04-28 19:36:19

标签: websocket tornado

Tornado文档没有评论tornado.web.authenticated装饰器与WebSocketHandler一起使用的任何用法。我只想向经过身份验证的用户授予websocket连接。

通过测试,似乎在initialize()上为连接建立握手时的GET请求调用了WebSocketHandler。因此,我可以想象通过检查cookie中是否存在有效的会话令牌来覆盖initialize()并检查用户是否以标准方式进行身份验证。

但是在我去参与之前 - 我想把它发给社区,看看这是不是正确的做法。

  1. 是否有一种简单快捷的方法让WebSocketHandler只能继续握手来设置连接 - 与tornado.web.authenticated装饰器的方式类似?

  2. 我很惊讶这不是内置的。我是否遗漏了一些关于websockets以及如何保护它们的内容?


  3. 修改 请通过覆盖_execute()方法而非initialize()方法查看下面的可能答案。

2 个答案:

答案 0 :(得分:1)

如果用户未获得授权,最好的方法是覆盖open()并使用错误代码调用self.close()。如果您确实想要返回HTTP错误而不是websocket错误,则可以覆盖prepare()。覆盖get()_execute()是脆弱的,不鼓励。

答案 1 :(得分:-1)

在发布后的一小时内回答我自己的问题道歉...但我想在下面得到这个想法。非常好奇,如果有一个更好的方法,因为它总是让我感到紧张,当我不得不诉诸于重写“下划线”方法并在流上写下低级别的消息......但似乎有效。

下面的处理程序在继续使用“_execute()”方法(检查GET请求并继续使用握手逻辑)之前检查身份验证。

import logging

import tornado.escape
import tornado.websocket


class AuthenticatedWebsocketHandler(tornado.websocket.WebSocketHandler):
    '''Only allows a request to open a websocket for a valid current user.
       This class assumes that the get_current_user() method is defined
       to check for a valid session id. (see Tornado docs).
    '''
    def _execute(self, *args, **kwds):
        if not self.current_user:
            logging.warn('Unauthorized attempt by {} to open websocket.'
                    .format(self.request.remote_ip))

            self.stream.write(tornado.escape.utf8(
                'HTTP/1.1 401 Unauthorized\r\n\r\n'
                'Not authenticated.'))

            self.stream.close()
            return

        super(AuthenticatedWebsocketHandler, self)._execute(*args, **kwds)

需要覆盖_execute()而不是initialize()的原因与Tornado如何为tornado.web.RequestHandler扩展tornado.websocket.WebSocketHandler的结构有关。似乎没有一种优雅的方式来退出IOloop,否则会有适当的响应。