Tornado中的secure cookie

在开始用Python的web框架Tornado的时候,以为Tornado中的get_secure_cookieset_secure_cookie是用来设置加密后的Cookie信息的,但今天看了源代码之后,发现情况并非如想象的那样,secure_cookie在Tornado中的作用是对Cookie值进行签名而已。新版本(v4.0)和老版本(1.0)相较而言,虽然增加了第二个版本的secure_cookie,但功能仍然是一样。

在Tornado 1.0中,使用的是SHA1进行签名,而在Tornado 4.0中的新版本中使用的是SHA256进行签名,同时输出的Cookie格式有差异——开始第一个数字是版本号(secure cookie使用的version,而非Tornado的版本)。

新版本的set_secure_cookie设置Cookie的相关源码如下:

## Tornado 4.0中web.py的部分源码## set_secure_cookie相关的源码MIN_SUPPORTED_SIGNED_VALUE_VERSION = 1MAX_SUPPORTED_SIGNED_VALUE_VERSION = 2DEFAULT_SIGNED_VALUE_VERSION = 2DEFAULT_SIGNED_VALUE_MIN_VERSION = 1class RequestHandler(object):    def set_cookie(self, name, value, domain=None, expires=None, path="/",                   expires_days=None, **kwargs):        name = escape.native_str(name)        value = escape.native_str(value)        if re.search(r"[\x00-\x20]", name + value):            raise ValueError("Invalid cookie %r: %r" % (name, value))        if not hasattr(self, "_new_cookie"):            self._new_cookie = Cookie.SimpleCookie()        if name in self._new_cookie:            del self._new_cookie[name]        self._new_cookie[name] = value        morsel = self._new_cookie[name]        if domain:            morsel["domain"] = domain        if expires_days is not None and not expires:            expires = datetime.datetime.utcnow() + datetime.timedelta(                days=expires_days)        if expires:            morsel["expires"] = httputil.format_timestamp(expires)        if path:            morsel["path"] = path        for k, v in kwargs.items():            if k == 'max_age':                k = 'max-age'            morsel[k] = v    def set_secure_cookie(self, name, value, expires_days=30, version=None,                          **kwargs):        self.set_cookie(name, self.create_signed_value(name, value,                                                       version=version),                        expires_days=expires_days, **kwargs)    def create_signed_value(self, name, value, version=None):        self.require_setting("cookie_secret", "secure cookies")        return create_signed_value(self.application.settings["cookie_secret"],                                   name, value, version=version)def create_signed_value(secret, name, value, version=None, clock=None):    if version is None:        version = DEFAULT_SIGNED_VALUE_VERSION    if clock is None:        clock = time.time    timestamp = utf8(str(int(clock())))    value = base64.b64encode(utf8(value))    if version == 1:        signature = _create_signature_v1(secret, name, value, timestamp)        value = b"|".join([value, timestamp, signature])        return value    elif version == 2:        def format_field(s):            return utf8("%d:" % len(s)) + utf8(s)        to_sign = b"|".join([            b"2|1:0",            format_field(timestamp),            format_field(name),            format_field(value),            b''])        signature = _create_signature_v2(secret, to_sign)        return to_sign + signature    else:        raise ValueError("Unsupported version %d" % version)def _create_signature_v1(secret, *parts):    hash = hmac.new(utf8(secret), digestmod=hashlib.sha1)    for part in parts:        hash.update(utf8(part))    return utf8(hash.hexdigest())def _create_signature_v2(secret, s):    hash = hmac.new(utf8(secret), digestmod=hashlib.sha256)    hash.update(utf8(s))    return utf8(hash.hexdigest())

?调用的关系如下:

-------------+--------------------------+--------------------------------+-----------------------------------+---------------------------------+--------------------------             |                          |                                |                                   |                                 |             |                          |                                |                                   |                                 |             |                          |                                |                                   |                                 |             |                          |                                |                                   |                                 | +-----------+---------+                |                                |                                   |                                 | |                     |                |                                |                                   |                                 | |  set_secure_cookie  |                |                                |                                   |                                 | |                     |                |                                |                                   |                                 | +-----------+---------+                |                                |                                   |                                 |             |                          |                                |                                   |                                 |             |              +-----------+-------------+                  |                                   |                                 |             |     invoke   |                         |                  |                                   |                                 |             +------------->|   create_signed_value   |                  |                                   |                                 |             |              |                         |                  |                                   |                                 |             |              +-----------+-------------+                  |                                   |                                 |             |                          |                                |                                   |                                 |             |                          |                 +--------------+-------------+                     |                                 |             |                          |     invoke      |                            |                     |                                 |             |                          +---------------->| create_signed_value(global)|                     |                                 |             |                          |                 |                            |                     |                                 |             |                          |                 +--------------+-------------+                     |                                 |             |                          |                                |                                   |                                 |             |                          |                                |                 +-----------------+-------------+                   |             |                          |                                | invoke          |                               |                   |             |                          |                                +---------------->| _create_signature_v2(global)  |                   |             |                          |                                |                 |                               |                   |             |                          |                                |                 +-----------------+-------------+                   |             |                          |                                |   return signature string (sha256)|                                 |             |                          | return source and signature    |<----------------------------------+                                 |             |          result          |<-------------------------------+                                   |                                 |             |<-------------------------|           string               |                                   |                                 |             |                          |                                |                                   |                                 |             |                          |                                |                                   |                                 |             |                          |                                |                                   |                  +--------------+----------+             |                          |                                |                                   |                  |                         |             +-------------------------- -------------------------------- ----------------------------------- ----------------->|       set_cookie        |             |                          |                invoke set_cookie to set secure_cookie              |                  |                         |             |                          |                                |                                   |                  +--------------+----------+             |                          |                                |                                   |                                 |             |                          |                                |                                   |                                 |             |                          |                                |                                   |                                 |             |                          |                                |                                   |                                 |             |                          |                                |                                   |                                 |             |                          |                                |                                   |                                 |             |                          |                                |                                   |                                 |

需要注意,在RequestHandler类中的create_signed_value方法调用的是web.py中的模块方法create_signed_value。在获取到返回结果之后,set_secure_cookie调用set_cookie,将secure cookie放入cookie内。

版本2的secure cookie和版本1的签名区别就在_create_signature_v2_create_signature_v1上。

Tornado中的secure cookie

相关文章:

你感兴趣的文章:

标签云: