Django Rest框架基于请求头的权限

Django Rest框架基于请求头的权限,django,django-rest-framework,permissions,Django,Django Rest Framework,Permissions,我正在用Django Rest框架构建一个Django应用程序,将其托管在我组织的域中。域实现自定义身份验证协议。当有人访问该域时,例如访问app1.domainname.com,他们会被重定向到组织的登录页面(login.domainname.com),并且必须使用其员工帐户登录。在用户经过身份验证后,用户将被重定向回其初始目标(app1.domain.com)。然后,用户的信息存储在发送到应用程序的HTTP请求的一些自定义头字段中。例如 GET / HTTP/2 Content-Type:

我正在用Django Rest框架构建一个Django应用程序,将其托管在我组织的域中。域实现自定义身份验证协议。当有人访问该域时,例如访问app1.domainname.com,他们会被重定向到组织的登录页面(login.domainname.com),并且必须使用其员工帐户登录。在用户经过身份验证后,用户将被重定向回其初始目标(app1.domain.com)。然后,用户的信息存储在发送到应用程序的HTTP请求的一些自定义头字段中。例如

GET / HTTP/2
Content-Type: 
User-Agent: ...
...
X-Username: johndoe1
X-Firstname: John
X-Lastname: Doe
X-Email: johndoe@domainname.com
etc.
我正在尝试为我的RESTAPI实现自定义权限,该权限在标题中查找这些字段,然后根据用户信息授权用户。这就是我目前的情况:

from rest_framework.permissions import BasePermission

allowed = ['johndoe1', 'dicksmith2', 'username3']

class CutomPerm(BasePermission):
    message = "You don't have permission to access this object"

    def has_object_permission(self, request, view, obj):
        print(request.headers)
        username = request.headers['X-Username']
        return username in allowed
但当我运行服务器时,似乎自定义头被传递到后端。对于某些请求,它们是,但最终用户未被授权,因为
具有对象权限
方法会引发
键错误

[10/Mar/2020 10:03:29] "GET /api/obj/ HTTP/1.1" 200 81
[10/Mar/2020 10:03:29] "GET /favicon.ico/ HTTP/1.1" 200 11
{'Content-Length': '', 'Content-Type': 'text/plain', 'Host': 'localhost:8000', 'Connection': 'keep-alive', etc., 'X-Username': 'johndoe1', 'X-Firstname': 'John', etc.}
Forbidden: /api/obj/1/
[10/Mar/2020 10:04:35] "GET /api/obj/1/ HTTP/1.1" 403 6581
{'Content-Length': '', 'Content-Type': 'text/plain', 'Host': 'localhost:8000', 'Connection': 'keep-alive', etc.} # no custom headers here
[10/Mar/2020 10:04:35] "GET /favicon.ico/ HTTP/1.1" 200 11
Internal Server Error: /api/obj/1/
Traceback (most recent call last):
  File "/path/to/project/venv/lib/python3.8/site-packages/django/core/handlers/exception.py", line 34, in inner
    response = get_response(request)
  File "/path/to/project/venv/lib/python3.8/site-packages/django/core/handlers/base.py", line 115, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "/path/to/project/venv/lib/python3.8/site-packages/django/core/handlers/base.py", line 113, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/path/to/project/venv/lib/python3.8/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
    return view_func(*args, **kwargs)
  File "/path/to/project/venv/lib/python3.8/site-packages/rest_framework/viewsets.py", line 114, in view
    return self.dispatch(request, *args, **kwargs)
  File "/path/to/project/venv/lib/python3.8/site-packages/rest_framework/views.py", line 505, in dispatch
    response = self.handle_exception(exc)
  File "/path/to/project/venv/lib/python3.8/site-packages/rest_framework/views.py", line 465, in handle_exception
    self.raise_uncaught_exception(exc)
  File "/path/to/project/venv/lib/python3.8/site-packages/rest_framework/views.py", line 476, in raise_uncaught_exception
    raise exc
  File "/path/to/project/venv/lib/python3.8/site-packages/rest_framework/views.py", line 502, in dispatch
    response = handler(request, *args, **kwargs)
  File "/path/to/project/venv/lib/python3.8/site-packages/rest_framework/mixins.py", line 54, in retrieve
    instance = self.get_object()
  File "/path/to/project/venv/lib/python3.8/site-packages/rest_framework/generics.py", line 99, in get_object
    self.check_object_permissions(self.request, obj)
  File "/path/to/project/venv/lib/python3.8/site-packages/rest_framework/views.py", line 343, in check_object_permissions
    if not permission.has_object_permission(request, self, obj):
  File "/path/to/project/project/app/permissions.py", line 11, in has_object_permission
    username = request.headers['X-Username']
  File "/path/to/project/venv/lib/python3.8/site-packages/django/http/request.py", line 388, in __getitem__
    return super().__getitem__(key.replace('_', '-'))
  File "/path/to/project/venv/lib/python3.8/site-packages/django/utils/datastructures.py", line 320, in __getitem__
    return self._store[key.lower()][1]
KeyError: 'X-Username'
请注意,在打印出来的两个标题字典中,第一个包含所有自定义标题,而第二个没有。 我认为这是因为在幕后发生了一些重定向,而到达rest框架权限检查的最终请求丢失了所有自定义头。是否仍然需要基于自定义标题检查权限?
谢谢

Django修改http头键

您必须以以下方式访问标题:

username=request.META.get('HTTP\u X\u username',无)
如果用户名:
#你的逻辑
通过
签出Django头文档:

谢谢,但不是这个。我在使用META时也会遇到同样的错误。此外,当无法访问标头时,我不能使用None,因为我必须使用标头字段中的用户名,并且它肯定会存在。打印request.META dict并检查其中的内容。如果在那里找不到头密钥,那么要么客户端没有发送它们,要么其他服务在请求到达Django服务器之前删除它们。我认为是后者。我正在打印META-dict,它基本上与headers-dict相同。可能一些中间件来回重定向,在这个过程中,忽略了自定义的header。我只是不知道如何修复它。请检查重定向请求的函数。它应该设置头,还应该检查头是否在重定向时保留。如果报头不存在,您应该使用403使请求失败,并返回它们丢失的位置。