简体   繁体   English

Django登录自定义身份验证在本地有效,但不能在生产服务器上使用

[英]Django Login Custom Auth works locally but not on production server

I implemented a custom Authentication Backend for my Django Project. 我为Django项目实现了自定义身份验证后端。 If I run Django locally, accessing the productive database, everything works properly. 如果我在本地运行Django,访问生产数据库,则一切正常。 But if I run the same Django App on the production server, It fails. 但是,如果我在生产服务器上运行相同的Django App,它将失败。

Here is my custom Authentication: 这是我的自定义身份验证:

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

Part of my settings: 我的部分设置:

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
}

My Login View: 我的登录视图:

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)

Here in the login view when I set a breakpoint, locally it shows the correct User Object in request.user but on production, it keeps saying, that it is an anonymous user. 在这里,当我设置断点时,在登录视图中的本地视图中,它在request.user显示了正确的User Object,但在生产环境中,它一直在说,这是一个匿名用户。

The part where it fails is the IsAuthenticated().hasPermission(request, None) as apparently the permission is not given here or IsAuthenticated resolves to False. 失败的部分是IsAuthenticated().hasPermission(request, None) ,因为此处显然未提供权限,或者IsAuthenticated解析为False。

Any idea, what I might got wrong here? 任何想法,我在这里可能会出错吗?

I found out, that mod_wsgi caused the problem, as it is not passing the authorization by default. 我发现,mod_wsgi引起了问题,因为默认情况下它未通过授权。

For all others, that experience the problem, see this section of the djangorestframework: 对于所有其他遇到此问题的人,请参见djangorestframework的以下部分:

Apache mod_wsgi specific configuration Apache mod_wsgi特定配置

Note that if deploying to Apache using mod_wsgi , the authorization header is not passed through to a WSGI application by default, as it is assumed that authentication will be handled by Apache, rather than at an application level. 请注意,如果使用mod_wsgi部署到Apache,则默认情况下不会将授权标头传递给WSGI应用程序,因为假定身份验证将由Apache处理,而不是在应用程序级别进行。

If you are deploying to Apache, and using any non-session based authentication, you will need to explicitly configure mod_wsgi to pass the required headers through to the application. 如果要部署到Apache并使用任何基于非会话的身份验证,则需要显式配置mod_wsgi以将所需的标头传递给应用程序。 This can be done by specifying the WSGIPassAuthorization directive in the appropriate context and setting it to 'On' . 这可以通过在适当的上下文中指定WSGIPassAuthorization指令并将其设置为'On'

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 django Override admin在本地不起作用 - django override admin works locally not on production django 通道在本地工作但在服务器上失败 - django channels works locally but fails on server 在生产服务器上导入数据时出错-在本地工作正常 - Error importing data on production server- locally works fine 为什么Amazon S3签名的URL在本地运行但不能在生产服务器上运行? - Why Amazon S3 signed URL works locally but not on production server? Django表单不在生产服务器上呈现 - 使用testserver在本地工作正常,并且单元测试在生产服务器上传递 - Django forms not rendering on production server - work fine locally with testserver, and unit tests pass on production server 为什么我的 Django 登录可以在开发服务器上运行而不是在生产服务器上运行? - Why does my Django login work on development server but not production server? Django PasswordResetTokenGenerator, check_token(user, token) 在生产中返回 False,本地工作正常 - Django PasswordResetTokenGenerator, check_token(user, token) returns False on Production, Locally Works Fine Flask 在本地工作,但不在服务器上? - Flask works locally, but not on a server? 如何使用 Django rest_auth 创建自定义登录视图? - how to create custom login view with Django rest_auth? Django 自定义身份验证 Model 无法从管理门户登录 - Django Custom Auth Model can't login from Admin portal
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM