我的用例是为重置密码api生成令牌。我正在用python中的危险库进行操作。 https://pythonhosted.org/itsdangerous/。
此令牌(具有重置密码链接)通过电子邮件转发给客户端,该令牌具有有效期限,该期限已过验证,密码重置后可以成功通过。
这里的问题是,一旦密码重置成功,我如何确保在到期期限内不能再次使用相同的令牌(电子邮件链接)。我可以看到它危险的URLSafeTimedSerializer可以在验证阶段帮助评估令牌的年龄。另一方面,TimedJSONWebSignatureSerializer可帮助设置生成令牌时的到期时间。请检查随附的代码段。
是否有更好的方法来强制使令牌过期?如果不是,保存令牌已使用状态的最佳方法是什么?
import itsdangerous
key = "test"
# signer = itsdangerous.URLSafeTimedSerializer(key)
signer = itsdangerous.TimedJSONWebSignatureSerializer(key, expires_in=5)
email = "email@test.com"
# token = email # to be used with URLSafeTimedSerializer
token = signer.dumps({"email": email})
print token
# print signer.loads(token, max_age=5) # to be used with URLSafeTimedSerializer
print str(signer.loads(token)["email"]) # to be used with TimedJSONWebSignatureSerializer
答案 0 :(得分:0)
生成并签名令牌后,令牌将一直有效直到过期。您不能再更改它。考虑到这一点,这还意味着您一旦对其负载进行了签名就不能更改其任何有效负载,否则它将变成无效的(由于无效的签名)。
但是,您可以做的一件事是在生成令牌并将密钥存储在数据库中之后生成唯一密钥("some_key"
)。最后,将发布给用户的令牌有效负载可能看起来像这样:{"email": email, "reset_key": "some_key"}
。
每次有人尝试重设密码时,您只需先验证该密钥即可允许或拒绝请求。
重置成功后,您只需从数据库中删除该密钥(或将其标记为无效)即可。即使令牌本身从过期的角度来看仍然有效,这也会使以下包含相同令牌的请求无效。
希望对您有帮助!
答案 1 :(得分:0)
我意识到这是一个较晚的答案,所以为其他人找到这个问题而添加了
另一种方法可能是使用布尔型会话变量,例如tokenused
,并在令牌反序列化后将其设置为True
;因此会使令牌的使用无效。
例如,在Flask中使用session
对象:
uid = {}
try:
if not session['tokenused']:
session['tokenused'] = True
s = Serializer(app.config['SECRET_KEY'])
uid = s.loads(token)
except Exception as err:
errors.internal_server_error(err)
return uid