You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django密码过期功能失效,如何设置2分钟密码有效期?

解决Django密码2分钟有效期设置问题

问题分析

你当前的配置和代码存在几个关键问题:

  • PASSWORD_RESET_TIMEOUT是重置密码链接的有效期,并非用户密码本身的有效期,这个配置和你要实现的功能无关。
  • models.py里的password_expiry用了TimeField,只能存储时间(如14:30:00),无法记录完整日期,没法准确计算密码是否过期;且auto_now_add=True只会在用户创建时设置一次,修改密码时不会更新这个时间。
  • login视图完全没有添加密码过期的检查逻辑,所以即使配置了字段也不会生效。

正确实现步骤

1. 修正models.py字段

把password_expiry改为DateTimeField,去掉auto_now_add=True,后续手动控制更新时机:

from django.db import models
from django.contrib.auth.models import User

class RegisterUser(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    mobile = models.CharField(max_length=100)
    # 改为DateTimeField,存储密码创建/修改的完整时间
    password_expiry = models.DateTimeField(null=True, blank=True)

    def __str__(self):
        return self.user.username

2. 确保密码更新时同步更新有效期

在用户创建、修改密码时,设置/更新password_expiry为当前时间,用信号实现示例:

# 在models.py末尾添加
from django.db.models.signals import post_save
from django.dispatch import receiver
from django.utils import timezone

@receiver(post_save, sender=User)
def set_initial_password_expiry(sender, instance, created, **kwargs):
    # 用户创建时,如果设置了密码,初始化有效期
    if created and instance.password:
        register_user, _ = RegisterUser.objects.get_or_create(user=instance)
        register_user.password_expiry = timezone.now()
        register_user.save()

@receiver(post_save, sender=User)
def update_password_expiry_on_change(sender, instance, **kwargs):
    # 检测密码是否修改,若修改则更新有效期
    if instance.pk:
        old_user = User.objects.get(pk=instance.pk)
        if old_user.password != instance.password:
            register_user, _ = RegisterUser.objects.get_or_create(user=instance)
            register_user.password_expiry = timezone.now()
            register_user.save()

3. 修改login视图添加过期检查

在登录验证通过后,检查密码是否超过2分钟有效期,若过期则拒绝登录并引导修改密码:

from django.shortcuts import render, redirect
from django.contrib import auth
from django.utils import timezone
from .models import RegisterUser

def login(request):
    if request.method == 'POST':
        uname = request.POST['uname']
        pwd = request.POST['pwd']
        user = authenticate(username=uname, password=pwd)
        if user is not None:
            if user.is_active:
                # 获取用户的密码有效期记录
                register_user = RegisterUser.objects.filter(user=user).first()
                if register_user and register_user.password_expiry:
                    # 计算当前时间与密码过期时间的差值(分钟)
                    time_diff = (timezone.now() - register_user.password_expiry).total_seconds() / 60
                    if time_diff > 2:
                        # 密码过期,跳转到修改密码页面
                        return redirect('password_change')
                # 密码未过期,正常登录
                auth.login(request, user)
                return redirect('home')
        # 验证失败,返回登录页(可添加错误提示)
        return render(request, 'login.html', {'error': '用户名/密码错误或密码已过期'})
    else:
        return render(request, 'login.html')

4. (可选)添加密码修改路由

在urls.py中配置Django自带的密码修改视图,让过期用户能修改密码:

from django.contrib.auth import views as auth_views

urlpatterns = [
    # ... 其他路由
    path('password-change/', auth_views.PasswordChangeView.as_view(template_name='password_change.html'), name='password_change'),
    path('password-change/done/', auth_views.PasswordChangeDoneView.as_view(template_name='password_change_done.html'), name='password_change_done'),
]

关键说明

  • 不要使用PASSWORD_RESET_TIMEOUT控制密码本身的有效期,这个配置仅针对密码重置邮件中的链接有效时长。
  • 必须在密码创建/修改时同步更新password_expiry,否则过期时间永远是用户创建时的时间,逻辑会出错。

内容的提问来源于stack exchange,提问作者Jerin Raju

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 08:07:28