tornado安全cookie
文章目录
tornado安全cookie
文章源代码过多,参照tornado源码看本文效果更佳
Secure Cookies
Cookies 是不安全的,可以被客户端轻易修改和伪造,Tornado 的 Secure Cookies 使用加密签名来验证 Cookie 数据是否被非法修改过,签名后的 Cookie 数据包括时间戳、 HMAC 签名和编码后的 cookie 值等信息。tornado.web.RequestHandler
通过 set_secure_cookie()
和 get_secure_cookie()
方法来设置和获取 Secure Cookies,因为 HMAC 签名密钥是由 tornado.web.Application
实例来提供的,所以在实例化 tornado.web.Application
时必须在 settings 中提供 cookie_secret
参数才能使用安全 Cookies。否则,self.require_setting("cookie_secret", "secure cookies")
会抛出未设置 cookie_secret 异常。
cookie_secret 参数是一个随机字节序列,用来制作 HMAC 签名,可以使用下面的代码来生成:
|
|
set_secure_cookie
方法是对 set_cookie
方法的包装,其中的value值调用create_signed_value()
实现,需要注意的是expires_days
这个参数与 get_secure_cookie 方法的 max_age_days
参数严格来讲没有必然的联系,我们可以使用一个小于 expires_days 的 max_age_days
值在服务端控制安全 Cookie 的有效期(这个是与安全 Cookie 中的时间戳比较得到的,后面会从代码中看到)。
|
|
create_signed_value
函数的代码及相关签名函数如下所示:
|
|
模块变量 DEFAULT_SIGNED_VALUE_VERSION
硬编码指示默认的签名版本是 2,除非调用 set_secure_cookie 时指定版本号。两个版本之间的数据格式看代码就很明确,版本 1 就是简单的 “value|timestamp|signature” 拼接,版本 2 多了几个字段,并且记录值的字符串长度,尤其是预留的 key_version
字段为后续轮流使用多个 cookie_secret 提供了支持,并且对整个字符串进行签名(版本 1 仅仅对 value 进行了签名),这样可以大大增加安全系数。这里额外提一下时间戳(timestamp)字段,由于客户端在发送 Cookie 时并不会提供有效期,为了能够准确控制有效期,这里将 Cookie 生成的时间戳写入值当中,以便后续在服务端进行有效期验证。
get_secure_cookie 方法
get_secure_cookie
方法签名中的 value 参数指的是通过 set_secure_cookie 加密签名后的 Cookie 值,默认是 None 则会从客户端发送回来的 Cookies 中获取指定名称的 Cookie 值作为 value,再进行签名验证,传入的 max_age_days
,min_version
将对 Cookie 做进一步比较验证,验证通过以后返回 base64 解码的 Cookie 值(也就是下面注释中说的不论 python 的版本,返回的是 byte string,与 get_cookie 方法不同。get_cookie 方法在 python3 中返回的是 unicode string。)。
|
|
除了要进行编码还要进行解码decode_signed_value
方法的相关代码如下所示:
|
|
_signed_value_version_re
正则表达式用于获取签名所用的版本号,对于旧版本(版本 1 )加密签名的 cookie 数据中没有版本号这个字段,默认取 1。然后与指定的 min_version 进行比较,仅当大于等于 min_version 才进行下一步验证。版本 1 由函数 _decode_signed_value_v1 验证,版本 2 由 函数 _decode_signed_value_v2 验证,这两个函数主要就是按照对应签名格式解析数据,并对目标签名和时间戳等字段进行比较验证。需要说一下的是由于版本 1 的设计缺陷,没有对 timestamp 进行签名,为了尽可能防止攻击者篡改时间戳来进行攻击, _decode_signed_value_v1 函数对 timestamp 执行了额外的检查(timestamp > clock() + 31 * 86400),但这个检查并不能完全杜绝此类攻击。这应该也是重新设计版本 2 的一个原因。
文章作者 oouxx
上次更新 2019-05-07