Django自定义用户模型登录失败:check_password验证不通过
Django自定义用户模型登录失败:check_password验证不通过
看起来你在自定义Django用户模型时遇到了登录密码验证失败的问题,我帮你梳理下核心原因和修复方案,应该能解决你的问题!
问题核心原因
你提到用了password_strength库的make_password来哈希密码,但登录时用的check_password大概率是Django自带的工具——这两个不同库的密码哈希/验证逻辑不兼容,自然会导致“密码无效”的错误。另外,直接给password字段手动赋值哈希值的方式,也不是Django推荐的标准做法,容易踩坑。
具体修复步骤
1. 改用Django配套的密码工具
Django自身的django.contrib.auth.hashers模块提供了完全兼容的make_password和check_password,先确保你导入的是这两个:
from django.contrib.auth.hashers import make_password, check_password
2. 用用户模型的set_password()方法设置密码(推荐)
不管是默认用户模型还是自定义模型,只要继承了AbstractBaseUser,就自带set_password()方法——这个方法会自动帮你处理密码哈希,比手动调用make_password更规范,也能避免哈希/验证不兼容的问题。
修改你的注册代码:
@csrf_exempt def signin_attempt(request): if request.method == 'POST': try: data = json.loads(request.body) email = data.get('email') password = data.get('password') username = data.get('username') stats = PasswordStats(password) validations = { "Password must be at least 8 characters long and contain at least one number and one special character": bool(policy.test(password)), "Password is too weak": stats.strength() < 0.5, "Username already exists": user.objects.filter(username=username).exists(), "Email already exists": user.objects.filter(email=email).exists(), } for message, condition in validations.items(): if condition: return JsonResponse({'success': False, 'message': message}, status=400) # 先创建用户实例,不直接赋值password user_obj = user(username=username, email=email) # 用set_password自动处理哈希 user_obj.set_password(password) user_obj.save() return JsonResponse({'success': True, 'message': "Sign in successful"}, status=201) except Exception as e: return JsonResponse({'success': False, 'message': f"Error: {str(e)}"}, status=500) return JsonResponse({'success': False, 'message': "Invalid request method"}, status=405)
3. 检查自定义用户模型的继承结构
确保你的user模型正确继承了Django的基类,这是set_password和check_password能正常工作的前提:
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager, PermissionsMixin from django.db import models class MyUserManager(BaseUserManager): def create_user(self, email, username, password=None): if not email: raise ValueError("Users must have an email address") user = self.model( email=self.normalize_email(email), username=username, ) user.set_password(password) user.save(using=self._db) return user class User(AbstractBaseUser, PermissionsMixin): email = models.EmailField(unique=True) username = models.CharField(max_length=100, unique=True) # 你的其他自定义字段... objects = MyUserManager() USERNAME_FIELD = 'email' # 设置邮箱为登录标识 REQUIRED_FIELDS = ['username']
4. 确保登录代码用的是Django的check_password
你的登录代码逻辑没问题,只要check_password是从django.contrib.auth.hashers导入的,验证就能正常通过。
额外小建议
- 尽量不要用
@csrf_exempt,可以在前端传递CSRF令牌,或者改用csrf_protect装饰器,提升接口安全性; - 自定义模型类名建议用大驼峰(比如
User而非user),符合Python的命名规范,也避免和内置名称冲突。
备注:内容来源于stack exchange,提问作者Aalok karn
相关产品推荐
相关产品推荐

