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

Django REST Framework单元测试403权限异常问题排查

DRF JWT认证单元测试返回403问题解决

问题成因

  • DRF的权限校验遵循逻辑与规则:配置的所有权限类必须全部校验通过才能放行,只要有一个不满足就直接返回403,不是满足任意一个即可。
    • IsAuthenticated仅校验请求携带有效认证凭证、用户处于登录状态
    • IsAdminUser额外要求登录用户必须是站点管理员,也就是用户模型的is_staff字段值为True
      测试代码里用create_user创建的是普通用户,默认is_staff=False,只要权限配置里带IsAdminUser,必然校验失败。
  • 测试代码里的JWT请求头前缀和SimpleJWT默认配置不匹配,导致认证失效。代码里写的认证头前缀是JWT,但SimpleJWT默认识别的认证头前缀是Bearer,前缀不对的时候认证后端解析不出有效用户,会把请求判定为匿名用户请求,这时候就算只配置IsAuthenticated权限,也会因为用户未登录返回403。
  • 全局权限配置会作用于所有没有显式指定permission_classes的视图,包括你用来获取token的MyTokenObtainPairView。这个接口本身是给未登录用户换取凭证用的,如果不单独放开权限,会被全局的登录校验拦截。

解决方法

  1. 按业务需求调整权限配置
    • 如果接口只要求登录即可访问,不需要管理员权限,直接删掉配置里的IsAdminUser,只保留IsAuthenticated
    • 如果接口确实需要管理员权限,创建测试用户时加上管理员标识:
      USER.objects.create_user(email=self.email, password=self.password, is_staff=True)
      
  2. 统一认证头前缀
    要么把测试代码里的认证头前缀改成和SimpleJWT默认一致的Bearer:
    self.client.credentials(HTTP_AUTHORIZATION=f"Bearer {token}")
    
    如果你要保留JWT作为前缀,就在settings里修改SimpleJWT配置:
    SIMPLE_JWT = {
        "AUTH_HEADER_TYPES": ("JWT",),
    }
    
  3. 给token获取接口单独放开匿名访问权限,避免被全局权限拦截:
    from rest_framework.permissions import AllowAny
    from rest_framework_simplejwt.views import TokenObtainPairView
    
    class MyTokenObtainPairView(TokenObtainPairView):
        permission_classes = [AllowAny]
        # 你的其他自定义逻辑
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 09:54:29