使用管理面板时,ModelBackend authenticate不接收凭据

2024-05-04 12:46:25 发布

您现在位置:Python中文网/ 问答频道 /正文

我已使用以下配置设置了自定义后端:

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提交请求时,它会按预期工作并正确验证用户等。当我尝试登录到管理面板时,我的问题就会出现。尝试登录时得到的堆栈跟踪是由于尝试访问request.data时出现异常引起的,这是因为它不是正确的类型,这与我的逻辑工作方式是正确的

问题是这里的身份验证方法

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知识有限),它就不会在我的后端找到具有正确参数的authenticate方法,所以它会回到默认值

登录错误的完整堆栈跟踪

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条回答
网友
1楼 · 发布于 2024-05-04 12:46:25

我通过添加到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)方法获取凭证,一旦登录到管理面板,我可以删除这一行,但理想情况下我想知道为什么它仍然这样做

相关问题 更多 >