pythonflaskitsdangerous

the "dumps" method of itsdangerous throws a TypeError


I am following the guide of 『Flask Web Development』.
I want to use itsdangerous to generate a token, but some problems occured. Here is my code:

def generate_confirmation_token(self, expiration=3600):
    s = Serializer(current_app.config['SECRET_KEY'], expiration)
    return s.dumps({'confirm': self.id})

The self.id is an int object.

But unfortunately,the "dumps" method throws a TypeError:

  File "/Users/zzx/projects/PycharmProjects/wurong/app/models.py", line 76, in generate_confirmation_token
    return s.dumps({'confirm': self.id})
  File "/Users/zzx/.pyenv/versions/3.6.1/envs/venv_blog/lib/python3.6/site-packages/itsdangerous.py", line 566, in dumps
    rv = self.make_signer(salt).sign(payload)
  File "/Users/zzx/.pyenv/versions/3.6.1/envs/venv_blog/lib/python3.6/site-packages/itsdangerous.py", line 353, in sign
    return value + want_bytes(self.sep) + self.get_signature(value)
  File "/Users/zzx/.pyenv/versions/3.6.1/envs/venv_blog/lib/python3.6/site-packages/itsdangerous.py", line 347, in get_signature
    key = self.derive_key()
  File "/Users/zzx/.pyenv/versions/3.6.1/envs/venv_blog/lib/python3.6/site-packages/itsdangerous.py", line 333, in derive_key
    return self.digest_method(salt + b'signer' +
TypeError: unsupported operand type(s) for +: 'int' and 'bytes'

I don't know why this problem occurred, I just follow the guide of my book~


Solution

  • The second argument to Serializer is salt, not expiration. expiration is not an argument to Serializer at all, it's an argument to TimedSerializer.loads called max_age.

    If you want a token that expires, use TimedSerializer and pass the expiration when you load the token, not when you create it.

    def generate_confirmation(self):
        s = TimedSerializer(current_app.secret_key, 'confirmation')
        return s.dumps(self.id)
    
    def check_confirmation(self, token, max_age=3600):
        s = TimedSerializer(current_app.secret_key, 'confirmation')
        return s.loads(token, max_age=max_age) == self.id