В MiddlewareMixin.__init__() отсутствует 1 необходимый позиционный аргумент: 'get_response'
Я создал пользовательское промежуточное ПО django и декоратор для аутентификации RESTful API, который я разрабатываю. Вот код промежуточного ПО, которое я разработал:
# myproject/middleware.py
import jwt
from django.conf import settings
from django.http import JsonResponse
from users.models import User
class JWTAuthenticationMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
excluded_paths = ['/auth/users/register/', '/auth/users/login/']
if any(request.path.startswith(path) for path in excluded_paths):
return self.get_response(request) # Skip JWT validation for excluded paths
token = request.COOKIES.get('jwt')
if token:
try:
decoded = jwt.decode(token, settings.SECRET_KEY, algorithms=["HS256"])
user = User.objects.get(id=decoded['id'])
request.user = user
except (jwt.ExpiredSignatureError, jwt.InvalidTokenError, User.DoesNotExist):
return JsonResponse({'error': 'Invalid or expired token'}, status=401)
else:
request.user = None
return self.get_response(request)
Вот код для декоратора:
# users/utils.py
from functools import wraps
from django.http import JsonResponse
from django.middleware.csrf import CsrfViewMiddleware
def token_required(view_func):
@wraps(view_func)
def _wrapped_view(view_class_instance, request, *args, **kwargs):
csrf_middleware = CsrfViewMiddleware()
# Check CSRF token
csrf_error = csrf_middleware.process_view(request, None, (), {})
if csrf_error:
return csrf_error
if not request.user:
return JsonResponse({'error': 'Token is missing or invalid'}, status=401)
return view_func(view_class_instance, request, *args, **kwargs)
return _wrapped_view
Вот один из видов, который выдает ошибку:
from rest_framework.views import APIView
from users.serializers import UserSerializer
from rest_framework.response import Response
from users.models import User
from rest_framework.exceptions import AuthenticationFailed
import jwt
from django.conf import settings
from users.utils import token_required
class UserView(APIView):
@token_required
def get(self, request):
token = request.COOKIES.get('jwt')
if not token:
raise AuthenticationFailed('Unauthenticated User!')
try:
payload = jwt.decode(token, settings.SECRET_KEY, algorithms=['HS256'])
except jwt.ExpiredSignatureError:
raise AuthenticationFailed("Token has expired! Login again")
user = User.objects.filter(id=payload['id']).first()
serializer = UserSerializer(user)
return Response(serializer.data)
А ошибка следующая:
MiddlewareMixin.init() missing 1 required positional argument: 'get_response'
Мне очень нужна помощь в том, чтобы заставить это работать. Версии Python и Django, которые я использую, - 3.12.3 и 5.0.4 соответственно.
Я перепробовал множество различных решений, но ни одно из них пока не помогло. Даже ChatGPT не может найти проблемы в этом маленьком кусочке кода.
Проблема не в классе JWTAuthenticationMiddleware
, который вы определили. Скорее всего, ошибка вызвана классом CsrfViewMiddleware
в вашем декораторе.
В Django 2.x и более поздних версиях классы промежуточного ПО должны инициализироваться параметром get_response
. Класс CsrfViewMiddleware
- это встроенный в Django класс middleware, который также подчиняется этому правилу. Однако вы не передаете параметр get_response
при инициализации класса CsrfViewMiddleware
.
Один из способов исправить это - использовать атрибут get_response
из объекта request
для инициализации класса CsrfViewMiddleware
. Однако этот процесс не так прост и может работать не так, как ожидалось.
Лучшим подходом будет использование встроенного в Django декоратора csrf_exempt
или декоратора csrf_protect
для обработки проверки токенов CSRF.
Вот как можно изменить декоратор, чтобы он использовал csrf_exempt
:
from django.views.decorators.csrf import csrf_exempt
def token_required(view_func):
@wraps(view_func)
def _wrapped_view(view_class_instance, request, *args, **kwargs):
if not request.user:
return JsonResponse({'error': 'Token is missing or invalid'}, status=401)
return csrf_exempt(view_func)(view_class_instance, request, *args, **kwargs)
return _wrapped_view
Однако использование csrf_exempt
отключит защиту CSRF для представления, что может быть нежелательно. Если вы хотите сохранить защиту от CSRF, вместо нее можно использовать декоратор csrf_protect
:
from django.views.decorators.csrf import csrf_protect
def token_required(view_func):
@wraps(view_func)
def _wrapped_view(view_class_instance, request, *args, **kwargs):
if not request.user:
return JsonResponse({'error': 'Token is missing or invalid'}, status=401)
return csrf_protect(view_func)(view_class_instance, request, *args, **kwargs)
return _wrapped_view
Не забудьте удалить из декоратора инициализацию csrf_middleware
и проверку токена CSRF.
Кроме того, обратите внимание, что Django Rest Framework (DRF) имеет встроенную поддержку аутентификации JWT и защиты CSRF. Возможно, вы захотите использовать встроенные функции DRF вместо того, чтобы создавать собственное решение.