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

Django测试访问/course接口返回403未授权问题排查与解决

问题解决:Django测试/course接口返回403 Forbidden(认证凭证未提供)

问题描述

在Django中测试/course接口时,已在setUp方法中调用/auth/login完成登录(确认setUp执行正常),但测试返回403 Forbidden错误,提示“Authentication credentials were not provided”。打印请求头发现HTTP_AUTHORIZATION的值为“Bearer ”(token为空),响应头未携带授权头。

错误日志:

ERROR:root:the exc is Authentication credentials were not provided. and context is {'view': <course.views.CourseApi object at 0x7fe78ba9ad10>, 'args': (), 'kwargs': {}, 'request': <rest_framework.request.Request: GET '/course'>} and response is <Response status_code=403, "text/html; charset=utf-8"> and code 400
WARNING:django.request:Forbidden: /course
response headers {'Content-Type': 'application/json', 'Vary': 'Accept, origin', 'Allow': 'GET, POST, PUT, DELETE, HEAD, OPTIONS', 'X-Frame-Options': 'DENY', 'Content-Length': '77', 'X-Content-Type-Options': 'nosniff', 'Referrer-Policy': 'same-origin', 'Cross-Origin-Opener-Policy': 'same-origin'}
F

问题根源

测试代码存在三个关键错误:

  • 使用requests.post发起登录请求,而非Django测试客户端self.client.post,导致测试环境上下文不统一,获取的token无法正确关联到测试客户端。
  • force_authenticate方法使用错误:DRF的force_authenticate需要传入user对象,而非token字符串,该方法无法直接通过token设置认证。
  • 手动设置请求头时,可能因之前的认证配置错误,导致token未被正确携带。

修复方案

步骤1:改用Django测试客户端发起登录请求

替换requests.post为self.client.post,利用测试客户端的模拟请求能力,确保测试环境上下文一致。

步骤2:正确设置客户端认证凭证

使用self.client.credentials()方法设置默认授权头,后续所有请求都会自动携带该头,无需手动重复设置。

步骤3:删除错误的force_authenticate调用

移除无效的force_authenticate代码,改用正确的凭证设置方式。

修改后的完整测试代码

from django.test import TestCase
from rest_framework.test import APIClient

class TestUrls(TestCase):
    def setUp(self):
        self.client = APIClient()
        # 使用测试客户端发起登录请求
        login_url = '/auth/login'
        login_data = {
            'email': '<my_email>',
            'password': '<my_password>',
            'token': 'Bearer <my_token_str>'
        }
        response = self.client.post(login_url, login_data, format='json')
        print(response.json())

        if response.status_code == 200:
            # 从响应中提取token
            self.token = response.json().get('payload').get('token')
            print(self.token)
            # 设置客户端默认授权头
            self.client.credentials(HTTP_AUTHORIZATION=f'Bearer {self.token}')
        else:
            raise AssertionError(f"登录失败,状态码: {response.status_code}")

    def test_course_view_url_is_resolved(self):
        # 无需手动设置headers,客户端会自动携带授权头
        response = self.client.get('/course')
        print("response headers", response.headers)
        self.assertEqual(response.status_code, 200)

额外说明

  • 如果你的项目使用的是DRF的TokenAuthentication(而非JWT),授权头格式应为Token {token},而非Bearer {token},需要根据实际认证方式调整。
  • 确保/auth/login接口返回的payload.token确实是有效的认证token,可通过打印self.token确认值不为空。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 22:13:44