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

#python #django #authentication

#python #django #аутентификация

Вопрос:

Я внедрил пользовательский сервер аутентификации для своего проекта Django. Если я запускаю Django локально, получая доступ к производственной базе данных, все работает должным образом. Но если я запускаю то же самое приложение Django на рабочем сервере, происходит сбой.

Вот моя пользовательская аутентификация:

 import hashlib
import logging

from django.contrib.auth.models import User

from QAServer import error_codes
from QAServer import exceptions
from QAServer.DataAccess.UserDAO import UserDAO
from QAServer.couchbase_util import ConnectionUtil

import constants as c

logger = logging.getLogger(__name__)


class CouchbaseBackend(object):
    _workaround_delimiter = "login "

    def authenticate(self, username=None, password=None):
        # ## workaround to suppress 401 responses when login  is provided in username
        # ## -> otherwise problem with browser behaviour!
        if username.find(CouchbaseBackend._workaround_delimiter) >= 0:
            split = username.split(CouchbaseBackend._workaround_delimiter)
            username = split[1]

        salt, user = self.get_user(username)

        if salt:
            pass_hash = hashlib.sha512(password   salt).hexdigest()
        else:
            pass_hash = hashlib.sha256(password).hexdigest()

        logger.debug(user.details)
        # ## authentication fallback
        if user.password == pass_hash:
            logger.debug(user.details)
            return user
        else:
            logger.info("### wrong password for user %s ###" % username)
            raise exceptions.PermissionError(error_code=error_codes.INVALID_CREDENTIALS_PROVIDED)

    def get_user(self, username):
        try:
            con = ConnectionUtil.get_prod_instance()
            dao = UserDAO(con)

            cb_user = dao.find_by_username(username)

            return self.convert_to_django_user(cb_user)
        except User.DoesNotExist as e:
            logger.error("### Get User Error (Couchbase Backend Authentication) ###")
            logger.error(e)
            logger.error("#########################################################")
            return None

    @staticmethod
    def convert_to_django_user(cb_user):
        user_name = cb_user[c.USERNAME]
        email = cb_user[c.EMAIL]
        password = cb_user[c.PASSWORD]
        salt = cb_user.get(c.SALT, None)
        user = None

        try:
            user = User(username=user_name, password=password)
            user.email = email
            user.username = user_name
            user.details = cb_user

        except Exception, e:
            logger.error("### convert user to django user ###")
            logger.error(e)
            logger.error("###################################")
        return salt, user
  

Часть моих настроек:

 AUTHENTICATION_BACKENDS = [
    'QASystem.couchbase_backend.CouchbaseBackend'
]

# Application definition

INSTALLED_APPS = [
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'django.contrib.admin',
    'corsheaders',
    'rest_framework',
    'QASystemBackend',
    'QASystem'
]


REST_FRAMEWORK = {
    'DEFAULT_PARSER_CLASSES': (
        'rest_framework.parsers.JSONParser',
    ),
    'DEFAULT_RENDERER_CLASSES': (
        'rest_framework.renderers.JSONRenderer',
    ),
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'QASystem.Authentication.authentication.BasicAuthentication',
    ),
    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.IsAuthenticated',
    ),
    'EXCEPTION_HANDLER': 'QASystem.exception_handler.exception_handler',
    'PAGINATE_BY': 10
}
  

Мой вид входа в систему:

 class LoginSet(viewsets.ViewSet):

    permission_classes = (AllowAny,)

    def __init__(self, *args, **kwargs):
        super(LoginSet, self).__init__(*args, **kwargs)
        self.user_dao = UserDAO(CBaseUtil.get_prod_instance())
        self.token_dao = LoginTokenDAO(CBaseUtil.get_prod_instance())

    def login(self, request):
        if IsAuthenticated().has_permission(request, None):
            user = self.user_dao.find_by_key(request.user.details[m.ID])

            logger.info("LoginView::get Login UserID: %s" % request.user.details[m.ID])

            response_obj = {
                m.USER: user_models.UserModelParser.prepare_response(user),
                m.LOGIN_TOKEN: self.token_dao.create_token_for_user(user[m.ID])[0]
            }

            return Response(response_obj)
        else:
            logger.error("LoginView::get Invalid Credentials UserID")
            raise exceptions.PermissionError(error_code=error_codes.INVALID_CREDENTIALS_PROVIDED)
  

Здесь, в представлении входа в систему, когда я устанавливаю точку останова, локально отображается правильный объект User в request.user , но на рабочем месте он продолжает говорить, что это анонимный пользователь.

Часть, в которой происходит сбой, является IsAuthenticated().hasPermission(request, None) поскольку, по-видимому, разрешение здесь не дано или IsAuthenticated принимает значение False .

Есть идеи, что я мог здесь сделать не так?

Ответ №1:

Я обнаружил, что mod_wsgi вызвал проблему, поскольку он не передает авторизацию по умолчанию.

Обо всех других, с которыми возникает проблема, смотрите этот раздел djangorestframework:

Специфичная конфигурация Apache mod_wsgi

Обратите внимание, что при развертывании с использованием Apache mod_wsgi заголовок авторизации по умолчанию не передается в приложение WSGI, поскольку предполагается, что аутентификация будет обрабатываться Apache, а не на уровне приложения.

Если вы развертываетесь в Apache и используете любую аутентификацию, не основанную на сеансе, вам нужно будет явно настроить mod_wsgi передачу требуемых заголовков в приложение. Это можно сделать, указав WSGIPassAuthorization директиву в соответствующем контексте и установив для нее значение 'On' .

 # this can go in either server config, virtual host, directory or .htaccess
WSGIPassAuthorization On