Django账户验证时check_token始终返回TRUE 二次点击链接未失效
问题根因
Django 内置的 PasswordResetTokenGenerator 生成 token 时,默认参与哈希计算的用户字段只有 password、last_login、is_active 三个。
你实现密码重置功能时,校验通过后会修改用户密码,密码哈希值发生变化,旧 token 自然校验失败;但账户验证逻辑里仅修改了 is_guest 字段,该字段不在默认的哈希因子范围内,修改后不会影响 token 校验结果,所以重复点击链接始终能通过校验。
解决方案
推荐自定义 Token 生成器,把 is_guest 字段加入哈希计算因子,步骤如下:
- 自定义继承自
PasswordResetTokenGenerator的专属校验类
from django.contrib.auth.tokens import PasswordResetTokenGenerator class AccountVerifyTokenGenerator(PasswordResetTokenGenerator): def _make_hash_value(self, user, timestamp): # 加入is_guest字段参与哈希计算 return f"{user.pk}{timestamp}{user.is_active}{user.password}{user.is_guest}" # 实例化全局调用对象 account_verify_token_generator = AccountVerifyTokenGenerator()
- 替换序列化器中的校验逻辑
将原有校验行:
if not PasswordResetTokenGenerator().check_token(user, token):
替换为:
if not account_verify_token_generator.check_token(user, token):
修改完成后,当你首次校验通过将 is_guest 改为 False 时,哈希值会发生变化,旧 token 后续校验都会返回 False,符合预期逻辑。
现有代码其他注意点
- 你当前使用
UserAccount.objects.get(pk=uidb64)查询用户,如果 uid 对应的用户不存在,会直接抛出DoesNotExist异常,不会走到后续if user is None的判断分支,建议改为捕获异常的写法,避免服务端报错:
try: user = UserAccount.objects.get(pk=uidb64) except UserAccount.DoesNotExist: raise AuthenticationFailed('Invalid account. Please contact support')
- 提示文案里的
contant是拼写错误,正确拼写为contact。
内容的提问来源于stack exchange,提问作者Luka Reeson
相关产品推荐
相关产品推荐

