python:具有危险的API令牌生成

时间:2015-09-24 13:52:43

标签: python security authentication flask

我正在按照“Flask Web Development”一书来实现基于令牌的身份验证。基本上,用户使用HTTP基本身份验证对他/她自己进行身份验证,并为其生成令牌:

s = Serializer(app.config['SECRET_KEY'], expires_in = 3600)
token = s.dumps({ 'id': user.id })

但只要idSECRET_KEY保持不变,它就会发生变化。我知道交易将通过HTTPS进行,但仍然认为动态令牌会更好。如何实现动态令牌?

1 个答案:

答案 0 :(得分:15)

如果您需要时间敏感的令牌,请改用TimedSerializer class

它不仅使用时间戳来形成签名(因此每次使用时都会生成新签名),但您也可以使用该时间戳限制令牌生存期

>>> from itsdangerous import TimedSerializer
>>> s = TimedSerializer('sekrit')
>>> token = s.dumps({'id': 'foobar'})
>>> token
'{"id": "foobar"}.COWWsA.dect1vZLaDdgFQUA1G_iTpPY3Hg'
>>> s.loads(token, max_age=3600)
{'id': 'foobar'}
>>> s.loads(token, max_age=0)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/mpieters/Development/venvs/stackoverflow-2.7/lib/python2.7/site-packages/itsdangerous.py", line 643, in loads
    .unsign(s, max_age, return_timestamp=True)
  File "/Users/mpieters/Development/venvs/stackoverflow-2.7/lib/python2.7/site-packages/itsdangerous.py", line 463, in unsign
    date_signed=self.timestamp_to_datetime(timestamp))
itsdangerous.SignatureExpired: Signature age 18 > 0 seconds

请注意,Serializer class实际上并不支持expires_in关键字参数,因此我怀疑您引用的代码实际上使用的是(未记录的)TimedJSONWebSignatureSerializer类(导入的)使用别名),其中 采用该关键字参数,并且还包含时间戳:

>>> from itsdangerous import TimedJSONWebSignatureSerializer as Serializer
>>> s = Serializer('sekrit', expires_in=3600)
>>> token = s.dumps({'id': 'foobar'})
>>> token
'eyJhbGciOiJIUzI1NiIsImV4cCI6MTQ0MzEwODAyMywiaWF0IjoxNDQzMTA0NDIzfQ.eyJpZCI6ImZvb2JhciJ9.eCD3zKK1lYT8cZ9w8g0YVpaF-1rR-k6UNCYq9dHmvGo'
>>> s.loads(token)
{'id': 'foobar'}
>>> s = Serializer('sekrit', expires_in=0)
>>> token = s.dumps({'id': 'foobar'})
>>> token
'eyJhbGciOiJIUzI1NiIsImV4cCI6MTQ0MzEwNDUwMCwiaWF0IjoxNDQzMTA0NTAwfQ.eyJpZCI6ImZvb2JhciJ9.Eiw3Eco7p61X-ikMxXS5dDVmjYmRSThcsMCxMyuA-r0'
>>> s.loads(token)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/mpieters/Development/venvs/stackoverflow-2.7/lib/python2.7/site-packages/itsdangerous.py", line 807, in loads
    date_signed=self.get_issue_date(header))
itsdangerous.SignatureExpired: Signature expired

由于包含时间戳,因此生成的令牌静态:

>>> s = Serializer('sekrit', expires_in=3600)
>>> token1 = s.dumps({'id': 'foobar'})
>>> token2 = s.dumps({'id': 'foobar'})
>>> from difflib import ndiff
>>> print '\n'.join(ndiff(token1.split('.'), token2.split('.')))
- eyJhbGciOiJIUzI1NiIsImV4cCI6MTQ0MzEwODIwMywiaWF0IjoxNDQzMTA0NjAzfQ
?                                        ^ ^                    ^^

+ eyJhbGciOiJIUzI1NiIsImV4cCI6MTQ0MzEwODIxMSwiaWF0IjoxNDQzMTA0NjExfQ
?                                        ^ ^                    ^^

  eyJpZCI6ImZvb2JhciJ9
- YmrKQTvZEWw4_JOOPn5uEk9QlZNla4o3Gvo09H1MXfM
+ ApeLrwT_R60pkvCYe4ihzJFPG55tGiJK6VSi6BKxAXM

这两个令牌虽然是由同一个序列化程序生成的,但实质上有所不同。