Восстановление пароля - срок действия токена Django никогда не истекает
Я установил систему восстановления пароля в своем приложении, которая работает довольно хорошо, однако я столкнулся с проблемой, связанной с выпущенным токеном, срок действия которого, очевидно, никогда не истекает, по крайней мере, когда он используется пользователем несколько раз.
Ссылка, отправленная по электронной почте пользователю, остается действительной даже после смены пароля x раз с использованием той же ссылки.
Я использую обычный способ, который я нашел в интернете с token_generator.make_token(user)
utils.py
from django.contrib.auth.tokens import PasswordResetTokenGenerator
from six import text_type
class AppTokenGenerator(PasswordResetTokenGenerator):
def _make_hash_value(self, user, timestamp):
return (text_type(user.is_active), text_type(user.pk), text_type(timestamp))
token_generator = AppTokenGenerator()
api_email.py
def send_email_user_account_password_recover(request, user, language):
try:
uidb64 = urlsafe_base64_encode(force_bytes(user.pk))
token = token_generator.make_token(user)
url_base = get_url_base(request)
email_text = emailText["user_account_password_recover"][language]
if language == "fr":
link_text = "Réinitialiser mon mot de passe"
activate_url = url_base + f"/fr/recover-password-authorised/{uidb64}/{token}/"
else:
link_text = "Reset my password"
activate_url = url_base + f"/en/recover-password-authorised/{uidb64}/{token}/"
context = {"title": email_text["title"],
"content": email_text["text"],
"url_base": url_base,
"link": activate_url,
"link_text": link_text,
"language": language}
html_content = render_to_string("email/email-template-extends.html", context)
text_content = strip_tags(html_content)
email = EmailMultiAlternatives(
subject=email_text["title"],
body=text_content,
to=[user.email])
email.attach_alternative(html_content, "text/html")
email.send(fail_silently=False)
logger.info(f"Email user password recover for user ({user.id_code}) sent from {EMAIL_HOST_USER} to {user.email}.")
return True
except:
logger.error(f"Email user password recover for user ({user.id_code}) could not be sent.")
return False
views.py
def AccountVerification(request, language=None, uidb64=None, verification_token=None):
if verification_token:
if not language:
if request.LANGUAGE_CODE == "fr":
return HttpResponseRedirect(f'/fr/verification/email/{uidb64}/{verification_token}/')
else:
return HttpResponseRedirect(f'/en/verification/email/{uidb64}/{verification_token}/')
id = force_text(urlsafe_base64_decode(uidb64))
user = api.charge_user_from_id(id)
try:
if not token_generator.check_token(user, verification_token):
logger.error(f"{get_first_part_log(request)} Link not valid anymore.")
if language == "fr":
messages.error(request, f"Le lien n'est plus valide.")
return HttpResponseRedirect("/fr/se-connecter/")
else:
messages.error(request, f"The link is not valid anymore.")
return HttpResponseRedirect("/en/login/")
if user.is_active:
logger.info(f"{get_first_part_log(request)} User already activated, redirect to login.")
if language == "fr":
return HttpResponseRedirect("/fr/se-connecter/")
else:
return HttpResponseRedirect("/en/login/")
user.is_active = True
user.is_email_validated = True
user.save()
logger.info(f"{get_first_part_log(request)} Charging email verification completed page.")
if language == "fr":
return render(request, "fr/authentication/email-verification-completed.html", {})
else:
return render(request, "en/authentication/email-verification-completed.html", {})
except:
logger.error(f"{get_first_part_log(request)} An error occurred.")
if language == "fr":
messages.error(request, f"Une erreur est survenue, contactez le support (support@linkimo.fr)")
return HttpResponseRedirect("/fr/se-connecter/")
else:
messages.error(request, f"An error occurred, please contact support (support@linkimo.fr)")
return HttpResponseRedirect("/en/login/")
else:
pass
Мой вопрос прост, как я могу удалить токен из записи или сделать его недействительным, если пользователь уже использовал его и успешно сменил пароль?
Заранее благодарю за помощь!
Это не полностью отвечает на ваш вопрос, поскольку я не думаю, что токены могут быть установлены как одноразовые, но вы можете уменьшить количество секунд, в течение которых токен действителен в файле setting.py. По умолчанию это 3 дня, как показано ниже.
PASSWORD_RESET_TIMEOUT = 259200 # По умолчанию: 259200 (3 дня, в секундах)
token_generator.check_token(user, verification_token)
если тайм-аут истек, вышеуказанное возвращает false