我正在尝试将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”似乎有效,但感觉不对。
我错过了什么吗?
答案 0 :(得分:19)
查看TokenAuthentication类,我看到正在检查的标头是'HTTP_AUTHORIZATION'而不是'Authorization'
不完全正确,在请求META
dict中进行查找时,它实际查找的标头不在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标头都将转换为META密钥 将所有字符转换为大写,用。替换任何连字符 下划线并在名称中添加HTTP_前缀。所以,例如,a 名为X-Bender的标题将映射到META密钥HTTP_X_BENDER。
Django有关使用测试客户端设置标头的文档:
但是,您可以使用关键字参数来指定一些默认标头。例如,这将在每个请求中发送
User-Agent
HTTP标头:c =客户端(HTTP_USER_AGENT ='Mozilla / 5.0')
答案 1 :(得分:5)
Tom's answer很好,但不完整。
您的代码可以在dev环境中使用runserver
),但如果您在WSGI服务器(在我的情况下是Apache)中尝试它,服务器可以删除Authorization标头!
您可以在Boone's Blog上找到一个很好的修补程序,以便您的Apache conf在请求中保留Authorization标头并使其工作正常:
RewriteEngine on
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization},L]