Я создаю приложение 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 словарях заголовка первый содержит все пользовательские заголовки, но второй нет. Я думаю, это потому, что за сценой происходит некоторое перенаправление, и последний запрос, который попадает в проверку разрешений остальной инфраструктуры, потерял все свои пользовательские заголовки. Есть ли способ проверить разрешения на основе пользовательских заголовков? Спасибо