Как заблокировать авторизацию пользователя для Django Rest Framework в пользовательском Middleware?
Здравствуйте, я создаю пользовательское промежуточное ПО в Django для DRF.
Чтобы при попытке пользователя получить доступ к любому из api промежуточное ПО выполняло некоторую операцию и определяло, авторизован ли пользователь для доступа к конечной точке или нет.
Мой код выглядит следующим образом:
class PermissionMiddleware(MiddlewareMixin):
def process_view(self, request, view_func, view_args, view_kwargs):
if request.path.startswith('/admin/'):
return None
if request.path.startswith('/api/'):
is_allowed = True
if not is_allowed:
return # < -- What needs to return to block the access
return None
Моя проблема в том, что я должен вернуть из метода для запрета доступа к api? Я могу вернуть None, если я хочу дать доступ. Но я хочу запретить доступ и вернуть некоторое сообщение из представления api, чтобы пользователь знал, что ему не разрешено.
Итак, вкратце:
- Что я должен вернуть из промежуточного ПО, чтобы заблокировать доступ?
- Как вернуть пользователю сообщение о том, что он не авторизован?
Спасибо
Я думаю, вы бы подняли
PermissionDenied
Ошибка, и это будет обработано соответствующим образом.
Эта ошибка будет обработана следующим образом:
https://docs.djangoproject.com/en/4.1/topics/http/middleware/#process-exception
Допустим, вы хотите ограничить доступ к вашей конечной точке.
- Для достижения этого у вас есть два метода представления:
check_permissions
- принимает решение о том, разрешен ли запрос и пользователь разрешено ли продолжить.check_object_permissions
- принимает решение о том, разрешено ли пользователю взаимодействовать с объектом. - Чтобы определить свою собственную логику валидации, вы можете подкласс
BasePermission
класс изrest_framework
:class YourCustomPermission(permissions.BasePermission): # Will be retrieved from the view's methods mentioned above custom_message = 'Your message.' def has_permission(self, request, view): if is_your_custom_request_logic_satisfied(request): return True return False def has_object_permission(self, request, view, obj): if is_your_custom_object_logic_satisfied(request, obj): return True return False
- И, наконец, ваше представление:
class APIView(View): ... permission_classes = [IsAuthenticated, YourCustomPermission] def check_permissions(self, request): for permission in self.get_permissions(): if not permission.has_permission(request, self): self.permission_denied( request, message=getattr(permission, 'custom_message', None), code=getattr(permission, 'code', None) ) def check_object_permissions(self, request, obj): for permission in self.get_permissions(): if not permission.has_object_permission(request, self, obj): self.permission_denied( request, message=getattr(permission, 'custom_message', None), code=getattr(permission, 'code', None) )
Вот хороший учебник для чтения.
Этот подход я использовал для получения ожидаемого результата. Таким образом, мне не нужно изменять представление api. Надеюсь, это поможет другим в будущем.
from django.http import JsonResponse
class PermissionMiddleware(MiddlewareMixin):
def process_view(self, request, view_func, view_args, view_kwargs):
if request.path.startswith('/admin/'):
return None
if request.path.startswith('/api/'):
is_allowed = True
if not is_allowed:
return JsonResponse(
{"detail": "Subscription Expired or Not Subscribed"},
status=403
)
return None