我的项目对某些端点需要两种身份验证方法:
使用 Postman 或 iOS 应用程序使用 API 时一切正常,但我无法在测试中进行身份验证。用户身份验证工作正常,但全局密钥失败。
这是 Postman 中 HTTP 标头的外观:
X-Api-Key: KEY_VALUE
Authorization: Token TOKEN_VALUE
我尝试使用 shell 中的代码进行验证,并且使用与测试中使用的完全相同的代码进行身份验证工作正常!只有在测试中它失败了,所以我不确定如何进一步调试。
您可以看到一个完整的项目 on github。
测试输出:
Creating test database for alias 'default'...
System check identified no issues (0 silenced).
F
======================================================================
FAIL: test (app.tests.MyTests)
----------------------------------------------------------------------
Traceback (most recent call last):
File ".../authtest/app/tests.py", line 21, in test
self.assertEqual(response.status_code, status.HTTP_200_OK)
AssertionError: 403 != 200
----------------------------------------------------------------------
Ran 1 test in 0.112s
FAILED (failures=1)
Destroying test database for alias 'default'...
当我用 python manage.py shell
打开 shell 并复制并粘贴测试代码时:
>>> from rest_framework.test import (APITestCase, APIRequestFactory, force_authenticate)
>>> from rest_framework import status
>>> from accounts.models import User
>>> from app.views import MyView
>>> user = User.objects.create(email="test@test.com")
>>> user.set_password('1234')
>>> factory = APIRequestFactory()
>>> API_KEY = "KIkKSSz7.ziURxOZv8e66f28eMLYwPNs7eEhrNtYl"
>>> headers = {"HTTP_X_API_KEY": API_KEY}
>>> request = factory.get('/myview', **headers)
>>> force_authenticate(request, user=user)
>>> response = MyView.as_view()(request)
>>> response.status_code
200
也用邮递员作品提出请求。知道这里发生了什么吗?
答案 0 :(得分:1)
问题是您在测试中传递的硬编码 API_KEY
不是导致状态 403 的有效密钥。我认为原因可能是 django 在运行测试和 djangorestframework-api 时使用了单独的测试数据库- key 使用 APIKey 模型生成 api_key。
您可以通过以下方式确认:
所以我可能建议生成一个新的有效 api_key 并传递它而不是硬编码的密钥。
在这里,我将分享一个更新的测试文件,说明如何进行测试
from rest_framework.test import (APITestCase, APIRequestFactory, force_authenticate)
from rest_framework import status
from accounts.models import User
from .views import MyView
from rest_framework_api_key.models import APIKey
class MyTests(APITestCase):
def test(self):
user = User.objects.create(email="test@test.com")
user.set_password('1234')
user.save()
factory = APIRequestFactory()
api_key, key = APIKey.objects.create_key(name="my-remote-service")
headers = {"HTTP_X_API_KEY": key}
request = factory.get('/myview', **headers)
force_authenticate(request, user=user)
response = MyView.as_view()(request)
self.assertEqual(response.status_code, status.HTTP_200_OK)