测试APIClient中的请求在两次身份验证后失败

问题描述 投票:0回答:1

升级到 django 5 后,我们的测试套件开始表现出奇怪的行为。我们正在使用DRF的APIClient,并且身份验证不再按预期工作。某些 API 请求返回

rest_framework.exceptions.NotAuthenticated
,状态代码为 403(顺便说一句,如果有人可以解释为什么此状态是 403 而不是 401,我将不胜感激)。

这看起来是任意的。在用户权限等方面实现相同的 2 个视图请求中,其中一个仅在测试期间返回 403 。在 Postman 中执行相同的调用不会重现该错误。 因此,由于上述错误,一些过去在 django 4 下通过的完全相同的测试用例在 django 5 下不再通过。我没能在一个最小的例子中重现这些案例。

然而,我复制的内容如下:

client.force_authenticate(user) client.get(url) # the user does not have permissions. response is 403, as expected client.force_authenticate(None) # "log out" user.user_permissions.add(permission) client.force_authenticate(user) response = client.get(url) # the now has permissions. response 200 is expected assert response.status_code == 200 # response status is 403
软件包版本是

django==5.0.3 djangorestframework==3.15.0 pytest==7.4.3 pytest-django==4.7.0
我做了一个

最小项目,可以观察到这一点。

据我测试,这种意外行为在 django 4 和 5 中都会发生。 我在这里使用测试客户端是否不正确?

django django-rest-framework pytest-django
1个回答
0
投票
文档中描述了此行为:

ModelBackend 在第一次访问后缓存用户对象的权限 需要获取它们进行权限检查的时间。这是 通常适合请求-响应周期,因为权限不是 通常在添加后立即检查(在管理中,对于 例子)。如果您正在添加权限并立即检查它们 之后,例如在测试或视图中,最简单的解决方案是 从数据库中重新获取用户。

权限缓存

解决方案:

client.force_authenticate(user=user) client.get("/test/") client.force_authenticate(user=None) user.user_permissions.add(permission) # Getting a new user instance. # user.refresh_from_db() does not clear cache user = get_object_or_404(User, pk=user.id) client.force_authenticate(user=user) response = client.get("/test/") assert response.status_code == 200
关于未经身份验证的请求返回的 

response.status_code

,DRF 文档中有以下相关信息:

当未经身份验证的请求被拒绝时,有两种情况 可能合适的不同错误代码。

HTTP 401 未经授权

HTTP 403 权限被拒绝

HTTP 401 响应必须始终包含 WWW-Authenticate 标头,该标头指示 客户端如何进行身份验证。 HTTP 403 响应不包括 WWW-验证标头。

将使用的响应类型取决于身份验证 方案。尽管可以使用多种身份验证方案,但仅 可以使用一种方案来确定响应的类型。首先 确定类型时使用视图上设置的身份验证类 的回应。

如果设置中未指定DEFAULT_AUTHENTICATION_CLASSES,则使用默认的:

[ 'rest_framework.authentication.SessionAuthentication', 'rest_framework.authentication.BasicAuthentication' ]
禁用 SessionAuthentication 类后,未经身份验证的请求将返回 401 响应。

© www.soinside.com 2019 - 2024. All rights reserved.