ValueError: Unsafe header value

ValueError: Unsafe header value

我使用 Tornado 4.2 开发了一个相当大的 Web 应用程序。我的应用程序的处理程序之一负责通过 post 请求验证用户的登录详细信息。

特别是在这个处理程序中,我使用带有 set_secure_cookie 的签名 cookie 来识别登录用户及其权限,使用以下代码:

self.set_cookie("user", self.get_argument("username"), domain=".my-domain.com", expires_days=None, httpOnly=True) 
self.set_secure_cookie("access", str(data['permissions']), expires_days=None, httpOnly=True)

设置 cookie 后,我使用 Tornado 的 redirect 将用户发送到另一个 URL。

self.redirect("/"+lang+"/base_fx.html")

在大多数情况下,它按预期工作,没有任何问题。但是,对于某些用户,我收到以下错误。

       self.redirect("/"+lang+"/base_fx.html")   
File "/usr/lib/python2.7/dist-packages/tornado/web.py", line 671, in redirect
        self.finish()   
File "/usr/lib/python2.7/dist-packages/tornado/web.py", line 934, in finish
        self.flush(include_footers=True)   
File "/usr/lib/python2.7/dist-packages/tornado/web.py", line 884, in flush
        self.add_header("Set-Cookie", cookie.OutputString(None))   
File "/usr/lib/python2.7/dist-packages/tornado/web.py", line 339, in add_header
        self._headers.add(name, self._convert_header_value(value))   
File "/usr/lib/python2.7/dist-packages/tornado/web.py", line 369, in
    _convert_header_value
        raise ValueError("Unsafe header value %r", value) 
ValueError: ('Unsafe header value %r', 'access="2|1:0|10:1485161516|6:access|3892:eydvd…<long string>..f0a2f8ad"; httponly; Path=/') 
ERROR:tornado.general:Cannot send error response after headers written

有没有人遇到过类似的问题?

查看 corresponding source code 给出了两个选项:

  1. 您的 cookie 值中包含无效字符。这只能在用户名中,因为 set_secure_cookie 方法正确地将它的给定值转义为 base64。请确保您的用户名不包含 invalid characters ([\x00-\x1f]) 或者 - 更好 - 也为用户名使用安全 cookie。

  2. 在我看来,发生这种情况的更可能原因是您的权限对象对于将其放入 cookie 来说太大了。 Tornado 将 cookie 值的长度限制为 4000(参见 source)。当使用安全 cookie 时,需要容纳的信息比您的数据多,而且您的数据被编码为 base64,这使得它更大。出于多种原因,将如此大的信息存储为 cookie 可能不是一个好主意(即它随每个请求一起发送,...)。您应该在服务器端保存该数据或使用与 cookie 不同的本地存储技术。

Georg Jung post 为我指明了正确的方向。我遇到的问题 ValueError: Unsafe header value 与两个现有的问题有关:Tornado 的 1473 and 1025 which have now been solved on the 4.3 版本。对我来说,问题是有些用户名比其他用户名长,导致这些用户名的 header 大小大于 4000。

因此,要正确解决此问题,您可以采取以下两种措施之一:

  1. 将您的 Tornado 更新到等于或高于 4.3 的版本。
  2. 或者不想升级的话,可以将header大小的限制增加到8000以上。您可以通过更改系统中安装的 Tornado 发行版中的文件 web.py 来做到这一点。

例如在 Debian 系统上路径是:

usr/lib/python3.2/dist-packages/tornado/web.py