14

我试图使用TokenAuthentication与我的意见之一。 如http://django-rest-framework.org/api-guide/authentication.html所述,我将从登录名中收到的令牌添加为HTTP标头,该标头在我发送的请求中称为:“授权”。Django TokenAuthentication缺少'授权'http标头

问题是在我的unittests认证失败。 展望TokenAuthentication类我看到被检查的标题是“HTTP_AUTHORIZATION”而不是“授权”

我使用的视图:

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

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

改变头为“HTTP_AUTHORIZATION”似乎工作,但感觉不对劲。

我错过了什么?

回答

16

展望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

编辑

request.META查找头Django文档:

随着CONTENT_LENGTH和CONTENT_TYPE的例外,因为上面给出, 请求中的任何HTTP标头将被转换为META密钥 将所有字符转换为大写,替换带有 的任何连字符下划线并为该名称添加HTTP_前缀。因此,例如,称为X-Bender的 标头将被映射到META密钥HTTP_X_BENDER。与测试客户端设置页眉

Django文档:

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

C =客户端(HTTP_USER_AGENT = '的Mozilla/5.0')

4

Tom's answer是好的,但不完成。

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

您可以在Boone's Blog找到一个很好的修复了你的Apache的conf保持Authorization头的请求,并使其发挥作用很大:

RewriteEngine on 
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization},L] 
+0

链接的博客是死的,但尖救了我的理智。不知道Apache/WSGI正在剥头文件! – twig 2018-01-14 22:18:09