In Tornado 1.0, the SHA1 is used for signing, and the new version in Tornado 4.0 is signed with SHA256 and the output cookie format is different-the first number is the version number (secure The version used by cookies, not tornado versions.
The new version of the Set_secure_cookie settings cookies related to the source code as follows:
The code is as follows |
Copy Code |
# # Tornado 4.0 web.py part of the source code
# # Set_secure_cookie Related source code
Min_supported_signed_value_version = 1
Max_supported_signed_value_version = 2
Default_signed_value_version = 2
Default_signed_value_min_version = 1
Class 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 ())
|
The relationship of the call is as follows:
The code is as follows |
Copy Code |
-------------+--------------------------+--------------------------------+-----------------------------------+- --------------------------------+--------------------------
| | | | |
| | | | |
| | | | |
| | | | |
+-----------+---------+ | | | |
| | | | | |
| 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 | | |
| | | | +--------------+----------+
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
|
It is to be noted that the Create_signed_value method in the RequestHandler class calls the module method Create_signed_value in web.py. After obtaining the return result, Set_secure_cookie calls Set_cookie and puts the secure cookie inside the cookie.
The signature difference between
Version 2 's Secure cookie and version 1 is on _CREATE_SIGNATURE_V2 and _CREATE_SIGNATURE_V1.