Django REST Framework结合MongoDB时无法用正确账号密码登录
Django + MongoDB 登录失败排查与解决
问题场景
我是Django新手,用MongoDB作为数据库搭建登录/注册功能,用户能成功注册,但输入正确的邮箱和密码登录时,始终返回Invalid email or password。相关代码如下:
serializers.py
class UserSerializer(serializers.ModelSerializer): class Meta: model = User fields = ('id', 'email', 'first_name', 'last_name', 'password')
models.py
class UserManager(BaseUserManager): def create_user(self, email, password=None, **extra_fields): if not email: raise ValueError('The Email field must be set') email = self.normalize_email(email) user = self.model(email=email, **extra_fields) user.set_password(password) user.save(using=self._db) return user def create_superuser(self, email, password=None, **extra_fields): extra_fields.setdefault('is_doctor', True) extra_fields.setdefault('is_superuser', True) return self.create_user(email, password, **extra_fields) class User(AbstractBaseUser): email = models.EmailField(unique=True) first_name = models.CharField(max_length=30) last_name = models.CharField(max_length=30) is_active = models.BooleanField(default=True) is_doctor = models.BooleanField(default=False) is_superuser = models.BooleanField(default=False) USERNAME_FIELD = 'email' REQUIRED_FIELDS = ['first_name', 'last_name'] objects = UserManager() def __str__(self): return self.email
views.py(登录逻辑)
@api_view(['POST']) @csrf_exempt def login_view(request): email = request.data.get('email') password = request.data.get('password') user = authenticate(request, email=email, password=password) if user is not None: login(request, user) serializer = UserSerializer(user) return Response(serializer.data) else: return Response({'error': 'Invalid email or password'}, status=status.HTTP_401_UNAUTHORIZED)
排查与解决步骤
1. 手动验证密码匹配情况
先绕过authenticate函数,直接查询用户并验证密码,定位问题环节:
@api_view(['POST']) @csrf_exempt def login_view(request): email = request.data.get('email') password = request.data.get('password') try: user = User.objects.get(email=email) # 打印日志确认用户和密码存储状态 print(f"找到用户: {user.email}") print(f"存储的密码哈希: {user.password}") if user.check_password(password): login(request, user) serializer = UserSerializer(user) return Response(serializer.data) else: print("密码不匹配") return Response({'error': 'Invalid email or password'}, status=status.HTTP_401_UNAUTHORIZED) except User.DoesNotExist: print("用户不存在") return Response({'error': 'Invalid email or password'}, status=status.HTTP_401_UNAUTHORIZED)
通过日志确认:
- 是否能正确查询到用户
- 存储的密码是否为Django标准哈希格式(如
pbkdf2_sha256$260000$xxxxxx$xxxxxx) check_password是否返回True
2. 检查注册逻辑的正确性
如果密码是明文存储,check_password必然验证失败。确保注册时使用UserManager的create_user方法(该方法会自动哈希密码),而非直接调用User.objects.create():
# 正确的注册视图示例 @api_view(['POST']) def register_view(request): serializer = UserSerializer(data=request.data) if serializer.is_valid(): user = User.objects.create_user( email=serializer.validated_data['email'], password=serializer.validated_data['password'], first_name=serializer.validated_data['first_name'], last_name=serializer.validated_data['last_name'] ) return Response(serializer.data, status=status.HTTP_201_CREATED) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
3. 确认MongoDB适配的基类
默认的AbstractBaseUser是为SQL数据库设计的,若使用MongoDB(如通过djongo或django-mongodb-engine),需确保模型基类正确适配MongoDB的存储逻辑,避免密码哈希存储异常。
4. 自定义认证后端(可选)
若默认authenticate函数无法适配MongoDB,可自定义认证后端:
在项目中创建backends.py:
from django.contrib.auth.backends import BaseBackend from .models import User class EmailBackend(BaseBackend): def authenticate(self, request, email=None, password=None, **kwargs): try: user = User.objects.get(email=email) if user.check_password(password) and user.is_active: return user except User.DoesNotExist: return None def get_user(self, user_id): try: return User.objects.get(pk=user_id) except User.DoesNotExist: return None
然后在settings.py中配置:
AUTHENTICATION_BACKENDS = [ 'your_app.backends.EmailBackend', ]
内容的提问来源于stack exchange,提问作者D Binara
相关产品推荐
相关产品推荐

