Django Разрешение Rest Framework на основе заголовка запроса - PullRequest
0 голосов
/ 10 марта 2020

Я создаю приложение Django с Django Rest Framework для размещения его в домене моей организации. Домен реализует собственный протокол аутентификации. Когда кто-то получает доступ к домену, скажем, 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.

Я пытаюсь реализовать пользовательское разрешение для моего REST API, которое ищет эти поля в заголовках, а затем авторизует пользователя на основе его пользовательской информации. Вот что у меня сейчас:

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

Но когда я запускаю сервер, кажется, что пользовательские заголовки передаются на сервер. Для некоторых запросов они есть, но в конечном итоге пользователь не авторизован, потому что метод has_object_permission вызывает KeyError:

[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'

Обратите внимание, что в распечатанных 2 словарях заголовка первый содержит все пользовательские заголовки, но второй нет. Я думаю, это потому, что за сценой происходит некоторое перенаправление, и последний запрос, который попадает в проверку разрешений остальной инфраструктуры, потерял все свои пользовательские заголовки. Есть ли способ проверить разрешения на основе пользовательских заголовков? Спасибо

1 Ответ

0 голосов
/ 10 марта 2020

Django изменяет ключи заголовка http.

Вы должны получить доступ к заголовку как:

username = request.META.get('HTTP_X_USERNAME', None)
if username:
    # your logic
    pass

оформить заказ Django документы заголовка: https://docs.djangoproject.com/en/3.0/ref/request-response/#django .http .HttpRequest.META

...