Tornado文档没有评论tornado.web.authenticated
装饰器与WebSocketHandler
一起使用的任何用法。我只想向经过身份验证的用户授予websocket连接。
通过测试,似乎在initialize()
上为连接建立握手时的GET请求调用了WebSocketHandler
。因此,我可以想象通过检查cookie中是否存在有效的会话令牌来覆盖initialize()
并检查用户是否以标准方式进行身份验证。
但是在我去参与之前 - 我想把它发给社区,看看这是不是正确的做法。
是否有一种简单快捷的方法让WebSocketHandler
只能继续握手来设置连接 - 与tornado.web.authenticated
装饰器的方式类似?
我很惊讶这不是内置的。我是否遗漏了一些关于websockets以及如何保护它们的内容?
修改
请通过覆盖_execute()
方法而非initialize()
方法查看下面的可能答案。
答案 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,否则会有适当的响应。