Tornado set_cookie()无效

时间:2017-03-20 09:09:43

标签: python http tornado setcookie

有我的代码:

class WebHandler(RequestHandler):

  def get(self):
    self.set_cookie('name1', 'value.1')
    self.set_cookie('name2', 'value.2')
    self.write('OK')

当我运行此代码时,Chrome浏览器不会设置cookie' name1'但仍然设置cookie' name2'。当我删除cookie值中的点字符时,它就是oke。如何设置多个带点符号的cookie?

1 个答案:

答案 0 :(得分:0)

在我看来,这个问题可能有点不完整,但我仍然会尽力回答,希望对您和其他人有所帮助。

Tornado 的 set_secure_cookie()get_secure_cookie() 函数发送和检索浏览器 cookie,可防止浏览器中的恶意修改。要使用这些函数,您必须在应用程序构造函数中指定 cookie_secret 参数。我们来看一个简单的例子。

应用程序将呈现一个页面,计算它在浏览器中重新加载的次数。如果没有设置 cookie(或者如果 cookie 被篡改),应用程序将设置一个值为 1 的新 cookie。否则,应用程序将从 cookie 中读取的值递增。

import tornado.httpserver
import tornado.ioloop
import tornado.web
import tornado.options
from tornado.options import define, options


define("port", default=8000, help="run on the given port", type=int)


class MainHandler(tornado.web.RequestHandler):
    def get(self):
        cookie = self.get_secure_cookie("count")
        count = int(cookie) + 1 if cookie else 1

        countString = "1 time" if count == 1 else "{} times".format(count)

        self.set_secure_cookie("count", str(count))

        self.write(
            """
            <html><head><title>Cookie Counter</title></head>
            <body><h1>You&rsquo;ve viewed this page {} times.</h1>
            </body></html>
            """.format(
                countString
            )
        )


if __name__ == "__main__":
    tornado.options.parse_command_line()
    settings = {
        "cookie_secret": "u5SXVuerTfyQTT7uTbu7HjqiqHnh8UsBm37J4Y5lwto="
    }

    application = tornado.web.Application([(r"/", MainHandler)], **settings)

    http_server = tornado.httpserver.HTTPServer(application)
    http_server.listen(options.port)
    try:
        tornado.ioloop.IOLoop.instance().start()
    except KeyboardInterrupt:
        print("Server has shut down.")

如果您在浏览器中检查 cookie 的值,您会注意到为 count 存储的值是 "count=\"2|1:0|10:1612910394|5:count|4:MQ==|e8c35def2daaec8da8ca5f3f1db63168f97027024a824d17b5e405f4f97c26ce\""。 Tornado 将 cookie 值编码为 Base-64 字符串,并将时间戳和 HMAC 签名附加到 cookie 内容。如果 cookie 的时间戳太旧(或来自未来),或者签名与预期值不匹配,则 get_secure_cookie() 函数假定 cookie 已被篡改并将 return None,好像cookie 尚未设置。

传递给 cookie_secret 构造函数的 Application 值应该是唯一的随机字符串。在 Python shell 中执行以下代码片段将为您生成一个:

>>> import base64, uuid
>>> base64.b64encode(uuid.uuid4().bytes + uuid.uuid4().bytes)
b'KeQWrXgiTjWQIEzcRbx0vV/IM/mYAEqvs+EtZ/5dvfs='

不过,Tornado 的安全 cookie 仍然容易被窥探。攻击者可能能够通过浏览器中的脚本或插件拦截 cookie,或者只是通过窃听未加密的网络数据。请记住,cookie 值是签名而不是加密。恶意程序能够读取存储的 cookie 并将其数据传输到任意服务器或通过将未经修改的请求发送到应用程序来伪造请求。因此,避免在浏览器 cookie 中存储敏感的用户数据非常重要。

我们还需要意识到用户可能会修改自己的 cookie,这可能会导致权限提升攻击。例如,如果我们将用户付费查看的剩余文章数量存储在 cookie 中,我们希望防止用户自己更新该数量以获取免费内容。 httponlysecure cookie 属性可以帮助防止此类攻击。

在 cookie 上设置安全属性会指示浏览器仅通过 SSL 连接传输 cookie。 (这有点令人困惑,但这与 Tornado 的安全 cookie 不同,后者更准确地描述为签名 cookie。)从 Python 2.6 版开始,Cookie 对象还支持 { {1}} 属性。包含此属性会指示浏览器使 JavaScript 无法访问 cookie,这可以防止跨站点脚本攻击读取 cookie 的值。

要启用这些功能,您可以将关键字参数传递给 httponlyset_cookie 方法。例如,一个安全的、仅限 HTTP 的 cookie(这不是 Tornado 签名)可以随电话一起发送:

set_secure_cookie

因为 Tornado 带有内置的 XSRF 保护。有关这方面的更多详细信息,请参阅 official documentation,您还可以查看我的 one 条答案,其中设置了 self.set_cookie('foo', 'bar', httponly=True, secure=True)