22

我正在尝试将 TokenAuthentication 与我的一种观点一起使用。如https://www.django-rest-framework.org/api-guide/authentication/中所述,我将从登录中收到的令牌添加为 HTTP 标头,在我发送的请求中称为:“授权”。

问题是在我的单元测试中,身份验证失败。查看 TokenAuthentication 类,我看到正在检查的标头是“HTTP_AUTHORIZATION”而不是“授权”

我正在使用的视图:

class DeviceCreate(generics.CreateAPIView):
    model = Device
    serializer_class = DeviceSerializer

    authentication_classes = (TokenAuthentication,)
    permission_classes = (IsAuthenticated,)

将标头更改为“HTTP_AUTHORIZATION”似乎可行,但感觉有些不对劲。

我错过了什么吗?

4

2 回答 2

22

查看 TokenAuthentication 类,我看到正在检查的标头是“HTTP_AUTHORIZATION”而不是“授权”

不太正确,在请求META字典中进行查找时,它实际查找的标头没有前面的HTTP_,因此实际上request.META.get('HTTP_AUTHORIZATION', '') 在请求中查找Authorization标头。

问题是在我的单元测试中身份验证失败将标头更改为“HTTP_AUTHORIZATION”似乎有效

我没有仔细检查测试客户端的外观,但我相信设置HTTP_AUTHORIZATION是你需要做的,相当于实际设置Authorization标题。如果您确实发出了一个 http 请求,您应该会发现设置 auth 标头的工作方式与您期望的完全一样。

请参阅request.META此处的文档:https ://docs.djangoproject.com/en/dev/ref/request-response/#django.http.HttpRequest.META

编辑

Django 文档中查找标题request.META

除了上面给出的 CONTENT_LENGTH 和 CONTENT_TYPE 之外,请求中的任何 HTTP 标头都通过将所有字符转换为大写、用下划线替换任何连字符并在名称中添加 HTTP_ 前缀来转换为 META 键。因此,例如,名为 X-Bender 的标头将映射到 META 键 HTTP_X_BENDER。

关于使用测试客户端设置标头的 Django 文档:

但是,您可以使用关键字参数来指定一些默认标题。例如,这将User-Agent在每个请求中发送一个 HTTP 标头:

c = 客户端(HTTP_USER_AGENT='Mozilla/5.0')

于 2013-02-27T14:24:36.897 回答
7

汤姆的回答很好,但并不完整。

您的代码可以在开发环境中正常工作(使用runserver),但如果您在 WSGI 服务器(在我的情况下为 Apache)中尝试它,服务器可以去除 Authorization 标头!

您可以在Boone 的博客上找到一个很好的 Apache conf 修复程序,以将 Authorization 标头保留在请求中并使其正常工作:

RewriteEngine on
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization},L]
于 2015-09-24T17:11:25.650 回答