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

时间:2015-04-29 00:25:02

标签: python tornado

Utilizing the Tornado library within Python I have come across a very unusual error. It seems that when I have decorated my file upload handler with '@tornado.web.stream_request_body' the webserver throws the error:

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

The code governing the upload is as follows:

@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("/")

where my BaseHandler is a web.RequestHandler subclass with various helper functions (retrieving user info from cookies and whatnot).

Within my HTML template, I have the appropriate xsrf function call as seen here:

<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>

and is generating the proper xsrf input within the browser:

<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>

When I turn off xsrf_cookies within the webserver settings, all is well and everything functions as normal. However I feel that this is not ideal.

While xsrf_cookies is set to False, if given a text file called "stuff.txt" with a body of "testfile" the output is:

------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--

From that output, my guess is that the xsrf value is being captured by the stream_request_body and not passed to the appropriate xsrf validation class.

Any help on this would be greatly appreciated. Thank you in advance!

1 个答案:

答案 0 :(得分:3)

Tornado目前(从版本4.1开始)不支持流式多部分上传。这意味着您希望流式传输的上传必须是简单的PUT,而不是将上传的数据与其他表单字段(如_xsrf)混合的POST。要在此方案中使用XSRF保护,您必须通过HTTP标头(X-Xsrf-Token)而不是通过表单字段传递XSRF令牌。不幸的是,这与非JavaScript网页表单上传不兼容;你必须有一个能够设置任意HTTP头的客户端。