Я ищу здесь пояснения.
Я создал приложение для реагирования, которое подключается к Django Rest Framework (DRF). Приложение полностью конфиденциально, что означает, что никто, не прошедший аутентификацию, ничего не может делать. Для этого я использовал TokenAuthentication (пока, потому что я думаю, что SessionAuthentication будет более безопасным).
Я изо всех сил пытаюсь понять это:
Я нашел способ заставить его работать: украсив мой класс представления с помощью @permission_classes((AllowAny, )), он просто отлично работает. Но меня это не устраивает.
Итак, почему это?
В моем файле настроек есть:
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.TokenAuthentication',
),
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated', )
}
В документации DRF (ссылка) говорится:
DELETE requests require the user to have the delete permission on the model.
Но мой пользователь является администратором, так зачем мне явно добавлять этот декоратор?
Что я делаю неправильно? Это не лучший способ сделать это. И почему он хорошо работает без декоратора, если я делаю запрос с помощью внешнего клиента API (например, Postman - я использую Paw) ??
Для справки это мой упрощенный класс представления:
@permission_classes((AllowAny, ))
class ObservationAPIView(APIView):
def delete(self, request, test_id, observation_id, format=None):
# see if my object exists
try:
obs_object_to_delete = Observation.objects.get(pk=observation_id)
test_obj = Test.objects.get(pk=test_id)
except ObjectDoesNotExist:
errormsg = {
'observation id': observation_id,
'test id': test_id,
'message': 'Cannot delete this object. Observation ID or test ID not found.'
}
return Response(errormsg, status=status.HTTP_404_NOT_FOUND)
# it exists, delete it
obs_object_to_delete.delete()
# return the test data (not the deleted object)
serializer = TestSerializer(test_obj, many=False)
return Response(serializer.data)
def patch(self, request, test_id, observation_id, format=None):
# there is also a PATCH function to allow for edits.
# This does work well without the decorator.
@opalczynski Глядя на мои инструменты разработчика, похоже, что заголовок отправлен, но когда я проверяю запрос на стороне DRF, заголовка больше нет! Но только в методах DELETE. В методах POST или GET DRF видит, что мой пользователь аутентифицирован.
Супер странно :( Вы подключаетесь к бэкэнду напрямую? Или через какой-нибудь балансировщик нагрузки (например, nginx?) - может быть, есть какие-то правила, которые отключают заголовок Auth при действии Удалить?
не в моей среде разработки. Я использую сервер разработки по умолчанию (запущенный с npm start) для своего интерфейса. И серверная часть работает в контейнере докеров, который запускает сервер с помощью этой команды: python3 manage.py runserver 0.0.0.0:8000
Снова глядя на журналы DRF, кажется, что мое внешнее приложение сначала отправляет вызов OPTIONS (я полагаю, часть предварительной проверки), мой сервер отвечает кодом 200 (так что я полагаю, все работает нормально), а затем никаких других вызовов не следует.





Почему это происходит?
Поскольку вы добавляете DEFAULT_PERMISSION_CLASSES глобально, (в settings) DRF будет использовать этот во всех представлениях на основе классов.
. Если вы хотите использовать дополнительные / настраиваемые классы разрешений для определенного представления, вы можете добавить его внутри класса представления с помощью атрибута permission_classes как,
class SampleView(APIView):
permission_classes = (MyCustomPermissionClass,)
....В вашем случае вам нужно override поведение по умолчанию для конкретного метода.
Итак, как переопределить классы разрешений по умолчанию для частного метода способом DRF?APIView класс метод под названием get_permissions(), который обрабатывает это
class SampleView(APIView):
def get_permissions(self):
if self.request.method == 'DELETE':
return [permission() for permission in (AllowAny,)]
return super(SampleView, self).get_permissions()
# your codeСпасибо за ответ, но мне не нужно знать, как добавить уровень разрешений для метода удаления. Я хочу понять, почему мой уровень разрешений по умолчанию (isAuthenticated) не работает для методов DELETE.
Нашел! В URL-адресе не было завершающей косой черты, указывающей на метод удаления.
Но вместо того, чтобы выдать ошибку 404 или что-то в этом роде, DRF ответил ошибкой 401 (Несанкционированный доступ). Это заставило меня искать ошибки в авторизации.
Но все еще озадачен этим: установив декоратор @permission_classes ((AllowAny,)), конечная косая черта, похоже, не нужна для продолжения моего интерфейса после предварительной проверки. Без декоратора (и, следовательно, с соответствующими разрешениями) React не хочет продолжать работу после предварительной проверки. Если вы добавите косую черту в конце URL-адреса, все будет нормально. и так, что здесь происходит? Обходит ли allowAny CORS? И требует ли CORS завершающих слэшей?
Если кто-нибудь сможет объяснить мне такое поведение, я был бы очень благодарен.
Спасибо, что посмотрели всех !!
У меня были похожие симптомы по другим причинам,
Может быть, история отладки будет кому-то полезна.
GET, POST, PUT - работает нормально, DELETE - не работает
если всем не дано разрешение «AllowAny».
при отладке запросов в views.py обнаружено, что
в последнем случае request.user == AnonymousUser и request.auth == none.
Причина - неправильный синтаксис запроса DELETE на стороне внешнего интерфейса
(в JS fetch(url, {method: "DELETE", headers, body})
неправильное расположение фигурных скобок для опций),
что привело к потере жатки и тела, вкл. Заголовок авторизации.
Здесь все выглядит нормально. Нет никакого волшебства - на мой взгляд, у вас есть ошибка в приложении реакции - что не передает заголовок авторизации при запросе на удаление. Что касается AllowAny - это плохое решение. По сути, это позволяет любому пользователю (тоже не авторизованному) выполнять действие удаления. Как я уже сказал - внимательно посмотрите на свой клиентский код.