在 Flask-Login token_loader 中加载令牌会引发 "BadTimeSignature: timestamp missing"

Loading token in Flask-Login token_loader raises "BadTimeSignature: timestamp missing"

我想使用 Flask-Login 的 token_loader 加载登录用户。我只希望令牌对 REMEMBER_COOKIE_DURATION 配置中设置的值有效。当我尝试加载令牌时,我得到 BadTimeSignature: timestamp missing。为什么会出现此错误以及如何解决?

@login_manager.token_loader
def load_token(token):
    """This metod is callback, which is used in
    the Login Manager inner logic for retrieving
    data from token.
        :returns User instance or None if token
        is invalid.
    """
    max_age = app.config["REMEMBER_COOKIE_DURATION"].total_seconds()
    data = login_serializer.loads(token, max_age=max_age)

    user = get_user_by_id(data[0])

    if user and data[1] == user.password:
        return user
    return None
  line 418, in _load_from_cookie
    user = self.token_callback(cookie)
  File "/home/peter/Lv-164.UI/ecomap/src/python/ecomap/user.py", line 127, in load_token
    data = login_serializer.loads(token, max_age = max_age)
  File "/usr/local/lib/python2.7/dist-packages/itsdangerous.py", line 643, in loads
    .unsign(s, max_age, return_timestamp=True)
  File "/usr/local/lib/python2.7/dist-packages/itsdangerous.py", line 437, in unsign
    raise BadTimeSignature('timestamp missing', payload=result)
BadTimeSignature: timestamp missing

您尝试加载的令牌不是使用 TimedSerializer 生成的,或者是无效的,因此无法找到时间戳进行比较。使用正确的序列化程序来生成和加载您的令牌。您还应该捕获这些异常并记录错误,因为仍然可以发送错误数据。

from flask import abort, flash
from itsdangerous import TimedSerializer, BadData, SignatureExpired

# define a timestamp serializer
login_serializer = TimedSerializer(app.secret_key, salt='login')
# generate the token with the user id (your example assumed a list)
token = login_serializer.dumps([user.id])
# load the token, but tell the user about expiration and log bad data
try:
    data = login_serializer.loads(token, max_age=max_age)
except SignatureExpired:
    flash('Login token is too old, you need to log in again.')
    abort(401)
except BadData as e:
    app.logger.exception('Bad login token "{}"', token)
    abort(401)

将用户密码直接放在令牌中是不安全的,因为令牌只是签名,没有加密。攻击者可以看到用户的密码散列是什么并尝试破解它。相反,要么省略密码(因为他们只有在使用正确密码成功登录后才能获得令牌),或者将其与有关用户的其他信息进行哈希处理。

validation = hash((user.username, user.password))
token = login_serializer.dumps([user.id, validation])

data = login_serializer.loads(token, max_age=max_age)
user = get_user_by_id(data[0])

if hash((user.username, user.password)) != data[1]:
    # did not validate