You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Django 3.1 + Python 3.7环境下,如何为依赖Cookie中JWT的APIView设置测试Cookie?

解决Django DRF测试时无法传入JWT Cookie的问题

看起来你遇到的核心问题有两个:一是DRF认证类可能没配置成从Cookie读取JWT,二是测试客户端的Cookie设置方式不对。下面一步步给你解决:

1. 先确保DRF能从Cookie中读取JWT

你的get_jwt_payload函数依赖request.auth,这说明DRF的认证机制需要先从Cookie里提取JWT并解析。默认的JSONWebTokenAuthentication是从Authorization头读取Token的,所以你需要调整配置或自定义认证类:

方法一:使用官方配置(适配rest_framework_jwt版本)

首先在settings.py里配置JWT的Cookie名称,并确保认证类正确:

# settings.py
REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
    ]
}

JWT_AUTH = {
    'JWT_AUTH_COOKIE': jwt_settings.JWT_AUTH_COOKIE,  # 和你代码里用的Cookie名称保持一致
}

方法二:自定义Cookie认证类(如果默认类不支持Cookie读取)

如果你的rest_framework_jwt版本默认不支持从Cookie取Token,就自定义一个认证类:

# 在你的app下新建authentication.py
from rest_framework_jwt.authentication import JSONWebTokenAuthentication
from rest_framework_jwt.settings import api_settings as jwt_settings

class CookieJWTAuthentication(JSONWebTokenAuthentication):
    def get_jwt_value(self, request):
        # 从Cookie中提取JWT令牌
        return request.COOKIES.get(jwt_settings.JWT_AUTH_COOKIE)

然后在settings.py里替换默认的认证类:

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'your_app.authentication.CookieJWTAuthentication',  # 替换成你的类路径
    ]
}

2. 测试客户端正确设置Cookie的方法

你之前尝试的几种方式都有小问题,下面是两种有效的测试方案:

方式一:请求时直接传递COOKIES参数

APIClientget方法直接传入COOKIES字典,这是最直接的方式:

def test_call_with_no_features(self):
    self.create_unknown_user = True
    username = "1-test"
    user = self.create_user(username=username)
    
    # 生成JWT令牌
    payload = {
        "username": username,
        "n_cnm": "My Funky Course",
        "n_rl": "urn:lti:role:ims/lis/Learner",
        "n_nb": "Standard service",
    }
    token = jwt_settings.JWT_ENCODE_HANDLER(payload)
    cookie_name = jwt_settings.JWT_AUTH_COOKIE
    cookies = {cookie_name: token}

    # 使用APIClient并传入Cookie
    client = APIClient()
    response = client.get('/api/features/', COOKIES=cookies)
    
    # 验证请求里的Cookie是否存在
    self.assertIn(cookie_name, response.request['COOKIES'])
    # 其他业务断言逻辑...

方式二:加载Cookie到客户端实例(复用Cookie场景)

如果需要多次请求复用同一个Cookie,可以用client.cookies.load()

def test_call_with_no_features(self):
    # ... 前面的用户创建、Token生成逻辑保持不变 ...
    cookies = {jwt_settings.JWT_AUTH_COOKIE: token}

    client = APIClient()
    client.cookies.load(cookies)  # 把Cookie加载到客户端实例
    response = client.get('/api/features/')
    
    # 验证响应状态和业务结果
    self.assertEqual(response.status_code, 200)

3. 额外注意事项

  • 去掉测试里多余的HTTP_AUTHORIZATION头设置:你的视图依赖Cookie验证,这个头会让DRF优先从Header读取Token,反而可能干扰Cookie的正常读取。
  • 确认jwt_settings.JWT_AUTH_COOKIE的值:打印这个变量,确保你设置的Cookie键和它完全一致(大小写敏感)。
  • 检查视图权限配置:你当前设置了AllowAny,权限不会拦截请求,后续如果要限制登录用户访问,需要调整permission_classes

这样调整后,你的测试应该能正确传入Cookie,request.COOKIES里就能看到JWT令牌,get_jwt_payload也能正常从request.auth获取解析后的payload了。

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

火山引擎 最新活动