在打开WebSocket时tornado出现403 GET警告

50 投票
3 回答
23165 浏览
提问于 2025-04-18 14:01

我找到了一段Python脚本,应该可以让我打开一个WebSocket。不过,当我在Linux终端尝试打开这个WebSocket时,收到了一个警告:[W 1402720 14:44:35 web:1811] 403 GET / (192.168.0.102) 11.02 ms。在终端窗口中,“连接已打开”、“连接已关闭”和“收到消息”的信息都没有显示出来。

import tornado.httpserver
import tornado.ioloop
import tornado.options
import tornado.web
import tornado.websocket

class MyHandler(tornado.websocket.WebSocketHandler):
        def open(self):
                print "connection opened"
                self.write_message("connection opened")

        def on_close(self):
                print "connection closed"

        def on_message(self,message):
                print "Message received: {}".format(message)
                self.write_message("message received")

if __name__ == "__main__":
        tornado.options.parse_command_line()
        app = tornado.web.Application(handlers=[(r"/",MyHandler)])
        server = tornado.httpserver.HTTPServer(app)
        server.listen(8888)
        tornado.ioloop.IOLoop.instance().start()

3 个回答

1

稍微修改了一下 @maxhawkdown 的解决方案。

from tornado.util import PY3

if PY3:
    from urllib.parse import urlparse  # py2

    xrange = range
else:
    from urlparse import urlparse  # py3


class ChatHandler(tornado.websocket.WebSocketHandler):
    CORS_ORIGINS = ['localhost']

    def check_origin(self, origin):
        parsed_origin = urlparse(origin)
        # parsed_origin.netloc.lower() gives localhost:3333
        return parsed_origin.hostname in self.CORS_ORIGINS
5

不要check_origin() 里随便设置 return True,因为这样会带来 安全隐患。应该使用一个允许的域名列表,举个例子:

def check_origin(self, origin):
    allowed = ["https://site1.tld", "https://site2.tld"]
    if origin in allowed:
        print("allowed", origin)
        return 1
112

请添加

def check_origin(self, origin):
    return True

在 MyHandler 类里,像这样

class MyHandler(tornado.websocket.WebSocketHandler):

    def check_origin(self, origin):
        return True

    def open(self):
        print "connection opened"
        self.write_message("connection opened")

    def on_close(self):
        print "connection closed"

    def on_message(self,message):
        print "Message received: {}".format(message)
        self.write_message("message received")

根据文档:

默认情况下,[check_origin] 会拒绝所有来自其他主机的请求。

这是为了防止浏览器中的跨站脚本攻击,因为 WebSockets 允许绕过通常的同源策略,并且不使用 CORS 头部。

再说一次:

这是一个重要的安全措施;在不了解安全影响的情况下,不要禁用它。特别是,如果你的身份验证是基于 cookie 的,你必须限制 check_origin() 允许的来源,或者为 WebSocket 连接实现自己的类似 XSRF 的保护。想了解更多,请查看 这些文章

链接

撰写回答