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。这个接口本身是给未登录用户换取凭证用的,如果不单独放开权限,会被全局的登录校验拦截。
解决方法
- 按业务需求调整权限配置
- 如果接口只要求登录即可访问,不需要管理员权限,直接删掉配置里的
IsAdminUser,只保留IsAuthenticated - 如果接口确实需要管理员权限,创建测试用户时加上管理员标识:
USER.objects.create_user(email=self.email, password=self.password, is_staff=True)
- 如果接口只要求登录即可访问,不需要管理员权限,直接删掉配置里的
- 统一认证头前缀
要么把测试代码里的认证头前缀改成和SimpleJWT默认一致的Bearer:
如果你要保留self.client.credentials(HTTP_AUTHORIZATION=f"Bearer {token}")JWT作为前缀,就在settings里修改SimpleJWT配置:SIMPLE_JWT = { "AUTH_HEADER_TYPES": ("JWT",), } - 给token获取接口单独放开匿名访问权限,避免被全局权限拦截:
from rest_framework.permissions import AllowAny from rest_framework_simplejwt.views import TokenObtainPairView class MyTokenObtainPairView(TokenObtainPairView): permission_classes = [AllowAny] # 你的其他自定义逻辑
内容的提问来源于stack exchange,提问作者finethen
相关产品推荐
相关产品推荐

