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

Django REST Framework中MongoDB与JWT集成失败问题排查

解决MongoEngine + Django REST Framework + Simple JWT的ObjectId认证问题

问题根源在于Simple JWT默认会将Token中的用户ID当作整数处理,但MongoDB的ObjectId是字符串格式,导致权限校验时查询用户出现类型不匹配错误。以下是具体解决步骤:

1. 确认CustomUser模型正确配置ObjectId主键

确保自定义用户模型使用ObjectIdField作为主键,并正确实现Django用户模型所需的核心方法与字段:

from mongoengine import Document, ObjectIdField, StringField, EmailField
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager

class CustomUserManager(BaseUserManager):
    def create_user(self, email, password=None, **extra_fields):
        if not email:
            raise ValueError('用户必须填写邮箱')
        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_staff', True)
        extra_fields.setdefault('is_superuser', True)
        return self.create_user(email, password, **extra_fields)

class CustomUser(Document, AbstractBaseUser):
    id = ObjectIdField(primary_key=True)
    email = EmailField(unique=True)
    username = StringField(max_length=255, unique=True)
    is_active = StringField(default=True)
    is_staff = StringField(default=False)
    is_superuser = StringField(default=False)

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['username']

    objects = CustomUserManager()

    def has_perm(self, perm, obj=None):
        return self.is_superuser

    def has_module_perms(self, app_label):
        return self.is_superuser

2. 自定义JWT认证后端,适配ObjectId

重写Simple JWT的认证逻辑,修改get_user方法,将Token中的字符串ID转为MongoDB的ObjectId进行查询:

# 在myapp下新建auth_backends.py文件
from rest_framework_simplejwt.authentication import JWTAuthentication
from bson.objectid import ObjectId
from django.contrib.auth import get_user_model

User = get_user_model()

class MongoJWTAuthentication(JWTAuthentication):
    def get_user(self, validated_token):
        user_id = validated_token['user_id']
        try:
            return User.objects.get(id=ObjectId(user_id))
        except User.DoesNotExist:
            return None

3. 更新配置文件,替换默认认证类

修改settings.py中的REST_FRAMEWORK配置,使用自定义的认证后端:

INSTALLED_APPS = [
    # 其他已安装应用
    'rest_framework',
    'rest_framework_simplejwt',
    'myapp',
]

AUTH_USER_MODEL = 'myapp.CustomUser'

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'myapp.auth_backends.MongoJWTAuthentication',  # 替换为自定义认证类的路径
    ],
}

SIMPLE_JWT = {
    'AUTH_HEADER_TYPES': ('Bearer',),
    'USER_ID_FIELD': 'id',
    'USER_ID_CLAIM': 'user_id',
}

验证效果

你的GetUsersAPI无需修改,配置完成后即可正常使用IsAuthenticated权限:

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from rest_framework.permissions import IsAuthenticated

class GetUsersAPI(APIView):
    permission_classes = [IsAuthenticated]

    def get(self, request):
        return Response(status=status.HTTP_200_OK)

以上修改后,JWT认证时会正确处理MongoDB的ObjectId格式用户ID,解决类型不匹配导致的报错。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 08:52:47