Django自定义用户模型重置密码后登录失败问题求助
Django自定义用户模型密码重置后登录失败问题
我在Django中开发邮箱密码重置系统,采用以username作为唯一标识的自定义用户模型myUser。目前能正常接收重置邮件,但重置密码后使用新密码登录时,系统提示“Invalid credentials”错误。以下是相关代码:
登录视图代码(views.py)
def ilogin(request): if request.method == 'POST': username = request.POST['username'] password = request.POST['password'] user = authenticate(request, username=username, password=password) if user is not None: login(request, user) messages.success(request, f'Welcome {username}!') return redirect('index') else: if myUser.objects.filter(username=username).exists(): messages.error(request, 'Invalid credentials provided.') else: print('eeeeeee') messages.error(request, f'Account with username "{username}" does not exist. Please create an account.') return redirect('login') # Redirect back to login page else: return render(request, 'user/login.html')
密码重置确认视图代码
def password_reset_confirm(request, token): try: reset_token = PasswordResetToken.objects.get(token=token) if not reset_token.is_valid: messages.error(request, 'This reset link is expired or invalid.') return redirect('login') if request.method == 'POST': new_password = request.POST.get('new_password') confirm_password = request.POST.get('cofirm_password') if new_password == confirm_password: user = reset_token.user print(user) user.set_password(new_password) user.save() reset_token.is_used = True reset_token.save() messages.success(request, 'Your password has been reset successfully.') return redirect('login') else: messages.error(request, 'Password do not match') return render(request, 'emails/password_reset_confirm.html') except PasswordResetToken.DoesNotExist: messages.error(request, 'Invalid password reset link') return redirect('login')
PasswordResetToken模型代码
from django.db import models from django.conf import settings from django.utils import timezone from django.contrib.auth import get_user_model # Create your models here. User = get_user_model()#created a custom user model to use username as unique identifier class PasswordResetToken(models.Model): user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE) token = models.CharField(max_length=100, unique=True) created_at = models.DateTimeField(default = timezone.now) is_used = models.BooleanField(default=False) validity_period = 300 #how long the token is valid(5 mins) def __str__(self): return f'Password reset token for {self.user.username}' class Meta: verbose_name_plural = 'Password Reset Tokens' @property def is_valid(self): return not self.is_used and (timezone.now() - self.created_at).total_seconds() < self.validity_period
自定义用户模型代码
from django.db import models from django.contrib.auth.models import AbstractBaseUser,BaseUserManager,PermissionsMixin # Create your models here. class myUserManager(BaseUserManager): def create_user(self,username,email,password=None, **extra_fields): if not username: raise ValueError('The username field must be included') if not email: raise ValueError('The email field must be provided') username = self.model.normalize_username(username) email = self.normalize_email(email) extra_fields.pop('email', None) user = self.model( username = username, email=email, **extra_fields ) user.set_password(password) user.save( using = self._db ) return user def create_superuser( self,username,email,password=None, **extra_fields ): extra_fields.setdefault( 'is_staff', True ) extra_fields.setdefault( 'is_superuser',True) return self.create_user( username, email, password, **extra_fields ) class myUser(AbstractBaseUser,PermissionsMixin): username = models.CharField( max_length = 255, unique=True ) email = models.EmailField( unique= True ) is_staff = models.BooleanField ( default=False ) is_active = models.BooleanField(default=True) date_joined = models.DateTimeField(auto_now_add=True) objects = myUserManager() USERNAME_FIELD = 'username' REQUIRED_FIELDS = ['email'] def __str__(self): return self.username class Meta: verbose_name = 'User' verbose_name_plural = 'Users'
问题排查与解决方案
1. 修正密码确认字段拼写错误
密码重置确认视图中,获取确认密码的字段名拼写错误:cofirm_password应为confirm_password。如果前端表单的name属性是正确的confirm_password,会导致获取到None,密码对比逻辑异常。修正代码:
confirm_password = request.POST.get('confirm_password')
2. 确认密码哈希保存正常
user.set_password(new_password)会自动哈希密码,重置后可打印user.password确认是否为哈希值(而非明文)。若为明文,说明set_password未正确调用或被覆盖。
3. 验证认证后端配置
确保settings.py中配置了正确的认证后端,默认后端适配自定义用户模型:
AUTHENTICATION_BACKENDS = [ 'django.contrib.auth.backends.ModelBackend', ]
4. 重新获取用户对象避免缓存问题
重置密码时,可重新从数据库获取用户实例,避免可能的缓存导致的更新失效:
user = myUser.objects.get(pk=reset_token.user.pk) user.set_password(new_password) user.save()
5. 检查用户is_active状态
确认用户的is_active字段为True(模型默认值为True),若用户被禁用,authenticate会返回None。
6. 测试基础登录功能
用myUser.objects.create_user()创建测试用户,直接尝试登录,确认基础登录逻辑正常,排除自定义用户模型本身的问题。
内容的提问来源于stack exchange,提问作者Sir Keith
相关产品推荐
相关产品推荐

