Fixed #16182: Increase timestamp precision on TimestampSigner. Thanks to Eric Florenzano.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@16356 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Andrew Godwin 2011-06-10 11:54:42 +00:00
parent 66436ad171
commit 44a2cbad35
2 changed files with 24 additions and 20 deletions

View File

@ -158,8 +158,12 @@ class Signer(object):
class TimestampSigner(Signer): class TimestampSigner(Signer):
def __init__(self, *args, **kwargs):
self.time_func = kwargs.pop('time', time.time)
super(TimestampSigner, self).__init__(*args, **kwargs)
def timestamp(self): def timestamp(self):
return baseconv.base62.encode(int(time.time())) return baseconv.base62.encode(int(self.time_func() * 10000))
def sign(self, value): def sign(self, value):
value = smart_str('%s%s%s' % (value, self.sep, self.timestamp())) value = smart_str('%s%s%s' % (value, self.sep, self.timestamp()))
@ -168,10 +172,10 @@ class TimestampSigner(Signer):
def unsign(self, value, max_age=None): def unsign(self, value, max_age=None):
result = super(TimestampSigner, self).unsign(value) result = super(TimestampSigner, self).unsign(value)
value, timestamp = result.rsplit(self.sep, 1) value, timestamp = result.rsplit(self.sep, 1)
timestamp = baseconv.base62.decode(timestamp) timestamp = baseconv.base62.decode(timestamp) / 10000.0
if max_age is not None: if max_age is not None:
# Check timestamp is not older than max_age # Check timestamp is not older than max_age
age = time.time() - timestamp age = self.time_func() - timestamp
if age > max_age: if age > max_age:
raise SignatureExpired( raise SignatureExpired(
'Signature age %s > %s seconds' % (age, max_age)) 'Signature age %s > %s seconds' % (age, max_age))

View File

@ -1,5 +1,3 @@
import time
from django.core import signing from django.core import signing
from django.test import TestCase from django.test import TestCase
from django.utils.encoding import force_unicode from django.utils.encoding import force_unicode
@ -98,19 +96,21 @@ class TestTimestampSigner(TestCase):
def test_timestamp_signer(self): def test_timestamp_signer(self):
value = u'hello' value = u'hello'
_time = time.time signer = signing.TimestampSigner('predictable-key',
time.time = lambda: 123456789 time=lambda: 123456789)
try: ts = signer.sign(value)
signer = signing.TimestampSigner('predictable-key') self.assertNotEqual(ts,
ts = signer.sign(value) signing.Signer('predictable-key').sign(value))
self.assertNotEqual(ts,
signing.Signer('predictable-key').sign(value))
self.assertEqual(signer.unsign(ts), value) self.assertEqual(signer.unsign(ts), value)
time.time = lambda: 123456800 signer = signing.TimestampSigner('predictable-key',
self.assertEqual(signer.unsign(ts, max_age=12), value) time=lambda: 123456800)
self.assertEqual(signer.unsign(ts, max_age=11), value) self.assertEqual(signer.unsign(ts, max_age=12), value)
self.assertRaises( self.assertEqual(signer.unsign(ts, max_age=11), value)
signing.SignatureExpired, signer.unsign, ts, max_age=10) self.assertRaises(
finally: signing.SignatureExpired, signer.unsign, ts, max_age=10)
time.time = _time
def test_timestamp_precision(self):
one = signing.TimestampSigner('key', time=lambda: 123.4567).sign('v')
two = signing.TimestampSigner('key', time=lambda: 123.4568).sign('v')
self.assertNotEqual(one, two)