[英]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.