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

React-Django登录系统JWT Cookie验证失败问题求助

问题描述

我用React+Django搭建了应用并实现登录页面,计划将JWT令牌存入Cookie来跟踪已登录用户、展示对应内容。但调用获取用户详情接口时,request.COOKIES无法获取到JWT Cookie,接口返回{'error': 'You are not logged in'},打印request.COOKIES得到的是AnonymousUser。已确认浏览器控制台中React和Django服务器均已设置该Cookie,且settings.py中已配置django-cors-headers相关中间件、CORS_ORIGIN_WHITELIST及CORS_ALLOW_CREDENTIALS = True。


存储登录信息的模型代码

class LoginDetails(AbstractUser):
    user_data = models.OneToOneField(UserData, on_delete=models.CASCADE, null = True)
    username = models.CharField(max_length=255, unique=True, null=True)
    password = models.CharField(max_length=255, null=True)  # 注意:生产环境建议使用哈希密码

    USERNAME_FIELD = 'username'
    def __str__(self):
        return self.username

登录视图代码

class LoginView(APIView):
    def post(self, request):
        username = request.data.get('username')
        password = request.data.get('password')

        # 验证用户名和密码是否都已提供
        if not username or not password:
            return Response({'error': 'Username and password are required.'}, status=status.HTTP_400_BAD_REQUEST)

        # 验证用户身份
        user = authenticate(username=username, password=password)

        if user is None:
            return Response({'error': 'Invalid username or password.'}, status=status.HTTP_401_UNAUTHORIZED)

        # 生成JWT令牌
        token = jwt.encode({'user_id': user.id}, 'your_secret_key', algorithm='HS256')
        response_data = {'token': token, 'Role': user.user_data.role}
        response = Response(response_data, status=status.HTTP_200_OK)
        response.set_cookie('jwt', token, httponly=True)

        return response

出现问题的用户详情视图代码

class GetUserDetails(APIView):
    def get(self, request):
        print(request.COOKIES)
        token = request.COOKIES.get('jwt')
        
    
        if token:
            try:
                # 解码JWT令牌获取用户ID
                payload = jwt.decode(token, 'secret', algorithms=['HS256'])
                user_id = payload.get('id')
                user = LoginDetails.objects.get(pk=user_id)

                user_data = user.user_data

                # 获取并格式化用户详情
                education_data = list(Education.objects.filter(user=user_data).values())
                work_experience_data = list(WorkExperience.objects.filter(user=user_data).values())

                data = {
                    'user': {
                        'fullName': user_data.fullName,
                        'gender': user_data.gender,
                        'aadhaarNumber': user_data.aadhaarNumber,
                        'dateOfBirth': user_data.dateOfBirth,
                        'maritalStatus': user_data.maritalStatus,
                        'emergencyContactName': user_data.emergencyContactName,
                        'address': user_data.address,
                        'phoneNumber': user_data.phoneNumber,
                        'emailID': user_data.emailID,
                        'emergencyContactNumber': user_data.emergencyContactNumber,
                        'jobTitle': user_data.jobTitle,
                        'departmentName': user_data.departmentName,
                        'joiningDate': user_data.joiningDate,
                        'employmentType': user_data.employmentType,
                        'relevantSkills': user_data.relevantSkills,
                    },
                    'education': education_data,
                    'workExperience': work_experience_data
                }
                return JsonResponse(data)
            except jwt.ExpiredSignatureError:
                return JsonResponse({'error': 'Token expired'}, status=401)
            except jwt.InvalidTokenError:
                return JsonResponse({'error': 'Invalid token'}, status=401)
            except LoginDetails.DoesNotExist:
                return JsonResponse({'error': 'User not found'}, status=404)
        else:
            return JsonResponse({'error': 'You are not logged in'}, status=401)

问题排查与修复方案

1. 统一JWT密钥

登录时编码用的密钥是'your_secret_key',解码时却用'secret',密钥不一致会导致解码失败。将解码代码中的密钥改为和编码时一致:

payload = jwt.decode(token, 'your_secret_key', algorithms=['HS256'])

2. 匹配Payload字段

登录时编码的Payload是{'user_id': user.id},解码时却尝试获取payload.get('id'),字段不匹配会拿不到用户ID。修改为:

user_id = payload.get('user_id')

3. 完善Cookie跨域配置

跨域场景下,设置Cookie时需补充必要参数,同时React端请求要携带凭证:

  • Django端修改Cookie设置:
response.set_cookie(
    'jwt', 
    token, 
    httponly=True,
    secure=True,  # 生产环境开启,仅HTTPS传输
    samesite='None',  # 跨域场景必须设为None,配合secure使用
    max_age=3600*24*7  # 设置Cookie有效期,比如7天
)
  • React端请求时添加withCredentials: true(以axios为例):
axios.get('/api/user-details', { withCredentials: true })

4. 检查中间件顺序

确保corsheaders中间件放在CommonMiddleware之前,settings.py中MIDDLEWARE配置示例:

MIDDLEWARE = [
    'corsheaders.middleware.CorsMiddleware',
    'django.middleware.common.CommonMiddleware',
    # 其他中间件...
]

5. 配置Cookie的Domain属性

若React和Django不在同一域名下,设置Cookie时需指定Domain:

response.set_cookie('jwt', token, httponly=True, domain='your-domain.com')

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 15:25:25