Django метод входа дает ошибку рекурсии - PullRequest
0 голосов
/ 10 января 2020

Я попытался создать пользовательское представление аутентификации, которое сохраняет пользователя в сеансе, используя login(request, user), но дает мне

максимальная глубина рекурсии, превышенная при вызове Python объекта

Я попытался импортировать метод входа в систему с помощью from django.contrib.auth import login as django_login, чтобы не перепутать методы, но он все еще не работал.

Аутентификация работает нормально без метода входа, но не спасает пользователя в сеансе, так что это бесполезно.

Вот полный views.py файл:

from django.utils.translation import ugettext as _
from rest_framework.permissions import AllowAny, IsAuthenticated
from rest_framework.authentication import SessionAuthentication, BasicAuthentication
from rest_framework.views import APIView
from rest_framework.response import Response
from rest.models import User
from .serializers import UserSerializer
from django.contrib.auth import get_user_model
from django.contrib.auth import authenticate as django_authenticate
from django.contrib.auth import login as django_login
from django.contrib.auth.hashers import check_password
import json

class UserCreateAPIView(generics.CreateAPIView):
    queryset = User.objects.all()
    serializer_class = UserSerializer
    permission_classes = (AllowAny,)

class Authentication(authentication.BaseAuthentication):

    def authenticate(self, request):
        email = request.POST.get('email', None)
        password = request.POST.get('password', None)
        if not email or not password:
            raise exceptions.AuthenticationFailed(_('No credentials provided.'))

        credentials = {
            get_user_model().USERNAME_FIELD: email,
            'password': password
        }

        user = django_authenticate(**credentials)

        if user is None:
            raise exceptions.AuthenticationFailed(_('Invalid username/password.'))

        if not user.is_active:
            raise exceptions.AuthenticationFailed(_('User inactive or deleted.'))

        django_login(request, user)
        return (user, None)  # authentication successful

class LoginView(APIView):
    authentication_classes = (SessionAuthentication, Authentication)
    permission_classes = (IsAuthenticated,)

    def post(self, request, format=None):
        content = {
            'user': str(request.user),
            'auth': str(request.auth),
        }
        return Response(content)

def CheckLoginView(requst):
    current_user = requst.user
    return current_user

Вот трассировка:

            response = get_response(request) …
▶ Local vars
/var/www/cnmb10a/venv/lib/python3.7/site-packages/django/core/handlers/base.py in _get_response
                response = self.process_exception_by_middleware(e, request) …
▶ Local vars
/var/www/cnmb10a/venv/lib/python3.7/site-packages/django/core/handlers/base.py in _get_response
                response = wrapped_callback(request, *callback_args, **callback_kwargs) …
▶ Local vars
/var/www/cnmb10a/venv/lib/python3.7/site-packages/django/views/decorators/csrf.py in wrapped_view
        return view_func(*args, **kwargs) …
▶ Local vars
/var/www/cnmb10a/venv/lib/python3.7/site-packages/django/views/generic/base.py in view
            return self.dispatch(request, *args, **kwargs) …
▶ Local vars
/var/www/cnmb10a/venv/lib/python3.7/site-packages/rest_framework/views.py in dispatch
            response = self.handle_exception(exc) …
▶ Local vars
/var/www/cnmb10a/venv/lib/python3.7/site-packages/rest_framework/views.py in handle_exception
            self.raise_uncaught_exception(exc) …
▶ Local vars
/var/www/cnmb10a/venv/lib/python3.7/site-packages/rest_framework/views.py in raise_uncaught_exception
        raise exc …
▶ Local vars
/var/www/cnmb10a/venv/lib/python3.7/site-packages/rest_framework/views.py in dispatch
            self.initial(request, *args, **kwargs) …
▶ Local vars
/var/www/cnmb10a/venv/lib/python3.7/site-packages/rest_framework/views.py in initial
        self.perform_authentication(request) …
▶ Local vars
/var/www/cnmb10a/venv/lib/python3.7/site-packages/rest_framework/views.py in perform_authentication
        request.user …
▶ Local vars
/var/www/cnmb10a/venv/lib/python3.7/site-packages/rest_framework/request.py in user
                self._authenticate() …
▶ Local vars
/var/www/cnmb10a/venv/lib/python3.7/site-packages/rest_framework/request.py in _authenticate
                user_auth_tuple = authenticator.authenticate(self) …
▶ Local vars
/var/www/cnmb10a/cnmb10a/rest/auth_api/views.py in authenticate
        django_login(request, user) …
▶ Local vars
/var/www/cnmb10a/venv/lib/python3.7/site-packages/django/contrib/auth/__init__.py in login
    if hasattr(request, 'user'): …
▶ Local vars
/var/www/cnmb10a/venv/lib/python3.7/site-packages/rest_framework/request.py in user
                self._authenticate() …
▶ Local vars
/var/www/cnmb10a/venv/lib/python3.7/site-packages/rest_framework/request.py in _authenticate
                user_auth_tuple = authenticator.authenticate(self) …
▶ Local vars
/var/www/cnmb10a/cnmb10a/rest/auth_api/views.py in authenticate
        django_login(request, user) …
▶ Local vars
/var/www/cnmb10a/venv/lib/python3.7/site-packages/django/contrib/auth/__init__.py in login
    if hasattr(request, 'user'): …
▶ Local vars
/var/www/cnmb10a/venv/lib/python3.7/site-packages/rest_framework/request.py in user
                self._authenticate() …
▶ Local vars
/var/www/cnmb10a/venv/lib/python3.7/site-packages/rest_framework/request.py in _authenticate
                user_auth_tuple = authenticator.authenticate(self) …
▶ Local vars
/var/www/cnmb10a/cnmb10a/rest/auth_api/views.py in authenticate
        django_login(request, user) …
▶ Local vars

Последние 4 методы просто повторяются снова и снова.

Ответы [ 2 ]

2 голосов
/ 10 января 2020

django.contrib.auth.authenticate вызовет сервер, чтобы попытаться аутентифицировать пользователя. Вызывая его в вашем бэкэнде аутентификации, он будет l oop навсегда, потому что django.contrib.auth.authenticate будет вызывать вас бэкэндом, который будет вызывать функцию и т. Д.

Так что вам нужно использовать метод аутентификации, которым вы являетесь пытается переопределить и вызвать super().authenticate(request) вместо django.contrib.auth.authenticate.

0 голосов
/ 18 января 2020

Проблема, похоже, заключалась в том, что функция django_login() вызывала написанную мной authenticate(), которая в свою очередь снова вызывала django_login(). Решением было удалить django_login() изнутри authenticate() и добавить его к LoginView(), чтобы оно выглядело так:

    authentication_classes = (SessionAuthentication, Authentication)
    permission_classes = (IsAuthenticated,)

    def post(self, request, format=None):
        content = {
            'user': str(request.user),
            'auth': str(request.auth),
        }
        django_login(request, request.user)
        return Response(content)
...