python-3.x 如何解决缺少1个必需的位置参数:Django中的'get_response'

jei2mxaa  于 2023-10-21  发布在  Python
关注(0)|答案(1)|浏览(149)

我是Django的新手,我想添加一个JWT认证中间件。我使用的是Django 4.2.6版本,我的中间件代码如下:

import jwt
from django.http import JsonResponse
from django.conf import settings
from django.utils.deprecation import MiddlewareMixin

class TokenMiddleware(MiddlewareMixin):
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        # Check if the request has an "Authorization" header
        authorization = request.META.get('HTTP_AUTHORIZATION')

        if authorization and authorization.startswith('Bearer '):
            token = authorization.split(' ')[1]

            jwks_client = jwt.PyJWKClient(settings.JWT_VERIFY_URL)
            header = jwt.get_unverified_header(token)
            key = jwks_client.get_signing_key(header["kid"]).key
            
            try:
                jwt.decode(token, key, [header["alg"]])

            except jwt.ExpiredSignatureError:
                return JsonResponse({'error': 'Token has expired'}, status=401)

            except jwt.DecodeError:
                return JsonResponse({'error': 'Token is invalid'}, status=401)
        else:
            return JsonResponse({'message': 'Authentication Bearer Token is required.'})

        response = self.get_response(request)
        return response

我已经在settings.py中注册了我的中间件。我一直在试图修复这个错误,但没有真正帮助。它在调用get_response时触发。对于这段代码,我得到了以下错误:

Traceback (most recent call last):
  File "/home/abdulai/projects/abdulai/holden/nyc-transactions/nyc-transactions-backend/venv/lib/python3.10/site-packages/django/core/handlers/exception.py", line 55, in inner
    response = get_response(request)
  File "/home/abdulai/projects/abdulai/holden/nyc-transactions/nyc-transactions-backend/venv/lib/python3.10/site-packages/django/core/handlers/base.py", line 197, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/home/abdulai/projects/abdulai/holden/nyc-transactions/nyc-transactions-backend/venv/lib/python3.10/site-packages/django/views/decorators/csrf.py", line 56, in wrapper_view
    return view_func(*args, **kwargs)
  File "/home/abdulai/projects/abdulai/holden/nyc-transactions/nyc-transactions-backend/venv/lib/python3.10/site-packages/django/views/generic/base.py", line 104, in view
    return self.dispatch(request, *args, **kwargs)
  File "/home/abdulai/projects/abdulai/holden/nyc-transactions/nyc-transactions-backend/venv/lib/python3.10/site-packages/rest_framework/views.py", line 492, in dispatch
    request = self.initialize_request(request, *args, **kwargs)
  File "/home/abdulai/projects/abdulai/holden/nyc-transactions/nyc-transactions-backend/venv/lib/python3.10/site-packages/rest_framework/views.py", line 394, in initialize_request
    authenticators=self.get_authenticators(),
  File "/home/abdulai/projects/abdulai/holden/nyc-transactions/nyc-transactions-backend/venv/lib/python3.10/site-packages/rest_framework/views.py", line 272, in get_authenticators
    return [auth() for auth in self.authentication_classes]
  File "/home/abdulai/projects/abdulai/holden/nyc-transactions/nyc-transactions-backend/venv/lib/python3.10/site-packages/rest_framework/views.py", line 272, in <listcomp>
    return [auth() for auth in self.authentication_classes]
TypeError: TokenMiddleware.__init__() missing 1 required positional argument: 'get_response'
[14/Oct/2023 14:10:41] "GET /user/ HTTP/1.1" 500 95495

我已经通过以下方式在settings.py注册了我的中间件。

MIDDLEWARE = [
    "django.middleware.security.SecurityMiddleware",
    "django.contrib.sessions.middleware.SessionMiddleware",
    "django.middleware.common.CommonMiddleware",
    "django.middleware.csrf.CsrfViewMiddleware",
    "django.contrib.auth.middleware.AuthenticationMiddleware",
    "django.contrib.messages.middleware.MessageMiddleware",
    "django.middleware.clickjacking.XFrameOptionsMiddleware",
    "my_app.middleware.TokenMiddleware",
    "corsheaders.middleware.CorsMiddleware",
]

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'my_app.middleware.TokenMiddleware',
    ],
    'DEFAULT_RENDERER_CLASSES': [
        'rest_framework.renderers.JSONRenderer',
        # Add other renderers as needed
    ]
    # Other DRF settings...
}
k3bvogb1

k3bvogb11#

你不应该使用MiddlewareMixinMiddlewareMixin是用于老式的中间件,但是你正在以新的方式编写它,所以:

class TokenMiddleware:  # !L! no MiddlewareMixin
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        authorization = request.META.get('HTTP_AUTHORIZATION')
        if authorization and authorization.startswith('Bearer '):
            token = authorization.split(' ')[1]
            jwks_client = jwt.PyJWKClient(settings.JWT_VERIFY_URL)
            header = jwt.get_unverified_header(token)
            key = jwks_client.get_signing_key(header['kid']).key
            try:
                jwt.decode(token, key, [header['alg']])
            except jwt.ExpiredSignatureError:
                return JsonResponse({'error': 'Token has expired'}, status=401)
            except jwt.DecodeError:
                return JsonResponse({'error': 'Token is invalid'}, status=401)
        else:
            return JsonResponse(
                {'message': 'Authentication Bearer Token is required.'}
            )
        return self.get_response(request)

至于DRF,您的TokenMiddleware * 不是 * 一个身份验证类,但在这里可能不需要,因为它将通过中间件。因此,您可以从AUTHENTICATION_CLASSES中删除以下内容:

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        # ' my_app.middleware.TokenMiddleware',  # 🖘 remove
    ],
    # …
}

相关问题