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

如何让force_authenticate设置的request.user在Django中间件执行时生效?

问题描述

我在使用APITestCase及自带的self.client编写测试时,通过self.client.force_authenticate认证用户。发现该操作由rest_framework.request.Request构造函数处理,而该构造函数在rest_framework/views.py(391)的initialize_request()中创建,执行时机晚于中间件。

在中间件断点处调试可见:

(Pdb) p request
<WSGIRequest: GET '/api/admin/products/'>
(Pdb) p request.user
<SimpleLazyObject: <django.contrib.auth.models.AnonymousUser object at 0x7f537e0aa9a0>>
(Pdb) p request._force_auth_user
<User: admin>

DRF设置的._force_auth_user已存在,但request.user尚未生效。想找简洁方法让force_authenticate设置的request.user在中间件执行时(至少在AuthenticationMiddleware之后)可用。

解决方法
  • 方法一:测试用例内手动同步
    在测试中调用force_authenticate后,直接将用户同步到客户端的原生请求对象上:
user = User.objects.get(username="admin")
self.client.force_authenticate(user=user)
# 同步用户到Django原生WSGIRequest的user属性
self.client.request.user = user
# 发起请求
response = self.client.get("/api/admin/products/")

这种方式适合单个测试的临时处理,无需修改全局配置。

  • 方法二:自定义中间件全局处理
    编写一个轻量中间件,放在AuthenticationMiddleware之后、DRF认证中间件之前,自动检测并同步_force_auth_user到request.user:
# 项目下的middleware.py文件
class ForceAuthSyncMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        if hasattr(request, "_force_auth_user"):
            # 替换原生request.user为DRF预设置的用户
            request.user = request._force_auth_user
            # 删除标记避免DRF后续重复处理
            delattr(request, "_force_auth_user")
        response = self.get_response(request)
        return response

在settings.py的MIDDLEWARE列表中添加该中间件,注意位置顺序:

MIDDLEWARE = [
    # ... 其他系统中间件
    "django.contrib.auth.middleware.AuthenticationMiddleware",
    # 必须放在AuthenticationMiddleware之后
    "your_app_name.middleware.ForceAuthSyncMiddleware",
    # DRF的认证中间件放在后面
    "rest_framework.middleware.AuthenticationMiddleware",
    # ... 其他自定义中间件
]

这种方式一劳永逸,所有测试和正常请求都会自动完成用户同步。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 10:10:07