ModelBackend authenticate не получает учетные данные при использовании панели администратора - PullRequest
0 голосов
/ 01 апреля 2020

Я настроил пользовательский бэкэнд со следующей конфигурацией:

Settings.py;

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework_simplejwt.authentication.JWTAuthentication',
        'users.backends.CustomUserBackend',
        'django.contrib.auth.backends.ModelBackend',
    ),
}

AUTHENTICATION_BACKENDS = ('users.backends.CustomUserBackend',)

backends.py

class CustomUserBackend(ModelBackend):

    def authenticate(self, request, username=None, password=None, **kwargs):

        if username is None:
            username = request.data.get("username")

        if password is None:
            password = request.data.get("password")

        ....
        return None

    def get_user(self, user_id):
        try:
            return User.objects.get(pk=user_id)
        except User.DoesNotExist:
            return None

При отправке запроса через мой API это работает как положено и аутентифицирует пользователя правильно et c. Моя проблема возникает, когда я пытаюсь войти в админку. Трассировка стека, которую я получаю при попытке входа в систему, вызвана исключительной ситуацией при попытке доступа к request.data, потому что это неправильный тип для просмотра, который соответствует тому, как работает мой logi c.

Проблема в том, что здесь используется метод аутентификации;

def authenticate(request=None, **credentials):
    """
    If the given credentials are valid, return a User object.
    """

    for backend, backend_path in _get_backends(return_tuples=True):
        print(backend)
        try:
            inspect.getcallargs(backend.authenticate, request, **credentials)
        except TypeError:
            # This backend doesn't accept these credentials as arguments. Try the next one.
            continue
        try:
            user = backend.authenticate(request, )
        except PermissionDenied:
            # This backend says to stop in our tracks - this user should not be allowed in at all.
            break
        if user is None:
            continue
        # Annotate the user object with the path of the backend.
        user.backend = backend_path
        return user

    # The credentials supplied are invalid to all backends, fire signal
    user_login_failed.send(sender=__name__, credentials=_clean_credentials(credentials), request=request)

Здесь учетные данные содержат данные для входа {'username': 'dan', 'password': '12345'}. Если я правильно понимаю этот метод (мои python знания ограничены), он не находит мой метод аутентификации в моем бэкэнде с правильными параметрами, поэтому он возвращается к значению по умолчанию?

Полная трассировка стека после ошибки входа в систему ;

Traceback (most recent call last):
  File ".../env/lib/python3.7/site-packages/django/core/handlers/exception.py", line 34, in inner
    response = get_response(request)
  File ".../env/lib/python3.7/site-packages/django/core/handlers/base.py", line 115, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File ".../env/lib/python3.7/site-packages/django/core/handlers/base.py", line 113, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File ".../env/lib/python3.7/site-packages/django/views/decorators/cache.py", line 44, in _wrapped_view_func
    response = view_func(request, *args, **kwargs)
  File ".../env/lib/python3.7/site-packages/django/contrib/admin/sites.py", line 407, in login
    return LoginView.as_view(**defaults)(request)
  File ".../env/lib/python3.7/site-packages/django/views/generic/base.py", line 71, in view
    return self.dispatch(request, *args, **kwargs)
  File ".../env/lib/python3.7/site-packages/django/utils/decorators.py", line 43, in _wrapper
    return bound_method(*args, **kwargs)
  File ".../env/lib/python3.7/site-packages/django/views/decorators/debug.py", line 76, in sensitive_post_parameters_wrapper
    return view(request, *args, **kwargs)
  File ".../env/lib/python3.7/site-packages/django/utils/decorators.py", line 43, in _wrapper
    return bound_method(*args, **kwargs)
  File ".../env/lib/python3.7/site-packages/django/utils/decorators.py", line 130, in _wrapped_view
    response = view_func(request, *args, **kwargs)
  File ".../env/lib/python3.7/site-packages/django/utils/decorators.py", line 43, in _wrapper
    return bound_method(*args, **kwargs)
  File ".../env/lib/python3.7/site-packages/django/views/decorators/cache.py", line 44, in _wrapped_view_func
    response = view_func(request, *args, **kwargs)
  File ".../env/lib/python3.7/site-packages/django/contrib/auth/views.py", line 63, in dispatch
    return super().dispatch(request, *args, **kwargs)
  File ".../env/lib/python3.7/site-packages/django/views/generic/base.py", line 97, in dispatch
    return handler(request, *args, **kwargs)
  File ".../env/lib/python3.7/site-packages/django/views/generic/edit.py", line 141, in post
    if form.is_valid():
  File ".../env/lib/python3.7/site-packages/django/forms/forms.py", line 180, in is_valid
    return self.is_bound and not self.errors
  File ".../env/lib/python3.7/site-packages/django/forms/forms.py", line 175, in errors
    self.full_clean()
  File ".../env/lib/python3.7/site-packages/django/forms/forms.py", line 377, in full_clean
    self._clean_form()
  File ".../env/lib/python3.7/site-packages/django/forms/forms.py", line 404, in _clean_form
    cleaned_data = self.clean()
  File ".../env/lib/python3.7/site-packages/django/contrib/auth/forms.py", line 214, in clean
    self.user_cache = authenticate(self.request, username=username, password=password)
  File ".../env/lib/python3.7/site-packages/django/contrib/auth/__init__.py", line 74, in authenticate
    user = backend.authenticate(request, )
  File ".../users/backends.py", line 12, in authenticate
    username = request.data.get("username")
AttributeError: 'WSGIRequest' object has no attribute 'data'

1 Ответ

0 голосов
/ 01 апреля 2020

Я временно исправил это, добавив в метод authenticate;

def authenticate(request=None, **credentials):
    """
    If the given credentials are valid, return a User object.
    """
    for backend, backend_path in _get_backends(return_tuples=True):

        try:
            inspect.getcallargs(backend.authenticate, request, **credentials)
        except TypeError:
            # This backend doesn't accept these credentials as arguments. Try the next one.
            continue
        try:
            user = backend.authenticate(request, **credentials)
        except PermissionDenied:
            # This backend says to stop in our tracks - this user should not be allowed in at all.
            break
        if user is None:
            continue
        # Annotate the user object with the path of the backend.
        user.backend = backend_path
        return user

    # The credentials supplied are invalid to all backends, fire signal
    user_login_failed.send(sender=__name__, credentials=_clean_credentials(credentials), request=request)

Так что теперь метод user = backend.authenticate(request, **credentials) принимает учетные данные, после входа в административную панель я могу удалить эту строку, но в идеале хотел бы знать, почему он это делает до сих пор.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...