tornado.web.stream_request_body:即使在 html 内输入 _xsrf,也会出现 _xsrf 丢失错误

tornado.web.stream_request_body: _xsrf missing error even with _xsrf input within html

利用 Python 中的 Tornado 库,我遇到了一个非常不寻常的错误。似乎当我用'@tornado.web.stream_request_body'装饰我的文件上传处理程序时,网络服务器抛出错误:

WARNING:tornado.general:403 POST /upload (ip-address): '_xsrf' argument missing from POST
WARNING:tornado.access:403 POST /upload (ip-address) 1.44ms

上传控制代码如下:

@tornado.web.stream_request_body
class Upload(BaseHandler):
    def prepare(self):
        print self.request.headers

    def data_received(self,chunk):
        print chunk

    @tornado.web.authenticated
    def post(self):
        self.redirect("/")

我的 BaseHandler 是一个 web.RequestHandler subclass,具有各种辅助功能(从 cookie 和诸如此类的东西中检索用户信息)。

在我的 HTML 模板中,我有适当的 xsrf 函数调用,如下所示:

<form enctype="multipart/form-data" action="/upload" method="post" id="upload_form" class="form-upload">
    {% raw xsrf_form_html() %}
    <input type="file" name="upFile" required/>
    <button class="btn btn-lg btn-primary btn-block-submit" type="submit">Submit</button>
</form>

并且正在浏览器中生成正确的 xsrf 输入:

<form enctype="multipart/form-data" action="/upload" method="post" id="upload_form" class="form-upload">
    <input type="hidden" name="_xsrf" value="2|787b7c6e|4a82eabcd1c253fcabc9cac1e374e913|1430160367"/>
    <input type="file" name="upFile" required/>
    <button class="btn btn-lg btn-primary btn-block-submit" type="submit">Submit</button>
</form>

当我在网络服务器设置中关闭 xsrf_cookies 时,一切正常,一切正常。不过我觉得这样不太理想。

虽然 xsrf_cookies 设置为 False,如果给定一个名为 "stuff.txt" 的文本文件,正文为 "testfile",则输出为:

------WebKitFormBoundary4iHkIqUNgfqVErRB
Content-Disposition: form-data; name="_xsrf"

2|787b7c6e|4a82eabcd1c253fcabc9cac1e374e913|1430160367
------WebKitFormBoundary4iHkIqUNgfqVErRB
Content-Disposition: form-data; name="upFile"; filename="stuff.txt"
Content-Type: text/plain

testfile
------WebKitFormBoundary4iHkIqUNgfqVErRB--

根据该输出,我的猜测是 xsrf 值被 stream_request_body 捕获并且没有传递给适当的 xsrf 验证 class.

如有任何帮助,我们将不胜感激。提前致谢!

Tornado 目前(从 4.1 版开始)不支持流式传输 multi-part 上传。这意味着您希望流式传输的上传必须是简单的 PUT,而不是将上传的数据与其他表单字段(如 _xsrf)混合的 POST。要在这种情况下使用 XSRF 保护,您必须通过 HTTP header (X-Xsrf-Token) 而不是通过表单字段传递 XSRF 令牌。不幸的是,这与 non-javascript 网络表单上传不兼容;你必须有一个能够设置任意 HTTP headers.

的客户端