Django登录将进行身份验证,但重定向仅在远程服务器上失败

时间:2019-07-11 04:24:03

标签: python mysql django django-authentication

我刚完成我的Web应用程序的构建,并将其迁移到数字海洋滴。我遇到的问题是我可以运行runserver 0.0.0.0:8000并使用服务器IP来访问我的主页,登录页面,注册等。此外,我还可以输入不正确的凭据并重定向回登录状态。再次。输入正确的凭据后,Django会挂断,直到我停止服务器。

在我的本地计算机上,我没有这个问题,通过局域网连接,我也能够成功登录。我的本地计算机连接到与Django prod服务器位于同一数据中心的Droplet上的数据库。

奇怪的是,根据我的数据库,尝试登录成功。问题似乎与重定向到我的视图有关。通过更改重定向到我的登录页面并在我的视图中添加打印语句,我可以看到认证后再也无法访问它。

两个实例中的Mysql版本相同。

在我的Django实例中:

  • 我可以从我的实例登录数据库
  • 我可以从实例manage.py shell创建新的超级用户
  • 我可以填写注册表单并创建一个新用户(但我的shell挂起,直到CTR + C)
  • 我可以登录并证明我已通过manage.py shell的身份验证
  • 我可以确认服务器没有删除标头
  • 我可以从manage.py shell来查询我的用户
  • 我没有收到任何错误
  • 我的服务器没有占用太多CPU
  • allowed_hosts = ['*']
  • 我已注释掉所有安全功能
  • NGINX和Gunicorn被禁用(启用它们时存在相同的问题)

我也已经在与数据库相同的实例上克隆了我的仓库。不幸的是,这不能解决我的问题。

我正在使用:python3.6.8 - Django 2.2.1 - MySQL 5.7

settings.py

import os
 
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))


SECRET_KEY = os.environ['SECRET_KEY']

DEBUG = True

ALLOWED_HOSTS = ['*']


# Application definition

INSTALLED_APPS = [
    #django builtin Imports
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'django.contrib.sites',

    #django installed pacakges imports
    'allauth',
    'allauth.account',
    'crispy_forms',
    'jquery',
    'rest_framework',
    'rest_framework_datatables',
    'chartjs',
    'sass_processor',
    'django_nose',

    #user built imports
    'users',
    'pages',
    'authenticated',
    'exchange',
    'celerytasks'

]

    REST_FRAMEWORK = {
    'DEFAULT_RENDERER_CLASSES': (
        'rest_framework.renderers.JSONRenderer',
        'rest_framework.renderers.BrowsableAPIRenderer',
        'rest_framework_datatables.renderers.DatatablesRenderer',
    ),
    'DEFAULT_FILTER_BACKENDS': (
        'rest_framework_datatables.filters.DatatablesFilterBackend',
    ),
    'DEFAULT_PAGINATION_CLASS': (
                  'rest_framework_datatables.pagination.DatatablesPageNumberPagination'
        ),
    'PAGE_SIZE': 3,
}


MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'django.contrib.auth.middleware.RemoteUserMiddleware',
]

TEST_RUNNER = 'django_nose.NoseTestSuiteRunner'


ROOT_URLCONF = 'rubillion.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': ['templates'],
        'APP_DIRS': True,
        'OPTIONS': {
            'libraries':{
                'file_exists': 'authenticated.templatetags.app_filters'
            },
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

WSGI_APPLICATION = 'rubillion.wsgi.application'

#SESSION_ENGINE = "django.contrib.sessions.backends.cache" 

DATABASES = {
    'default': {
        'HOST': os.environ['HOST'],
        'NAME': 'user_db',
        'ENGINE': 'django.db.backends.mysql',
        'USER': os.environ['DBUSER'],
        'PASSWORD': os.environ['DBPWD']
    },
    'auth_db': {
        'HOST': os.environ['HOST'],
        'NAME': 'user_db',
        'ENGINE': 'django.db.backends.mysql',
        'USER': os.environ['DBUSER'],
        'PASSWORD': os.environ['DBPWD']
    },
    'exchange_db': {
        'HOST': os.environ['HOST'],
        'NAME': 'exchange',
        'ENGINE': 'django.db.backends.mysql',
        'USER': os.environ['DBUSER'],
        'PASSWORD': os.environ['DBPWD']
    },
}

DATABASE_ROUTERS = ['rubillion.routers.ExchangeRouter',     'rubillion.routers.AuthRouter']
# Password validation
# https://docs.djangoproject.com/en/2.1/ref/settings/#auth-password-    validators

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME':     'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]


LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_L10N = True

USE_TZ = True


STATIC_URL = '/static/'
STATICFILES_DIRS = [
    os.path.join(BASE_DIR, "static")
]

AUTH_USER_MODEL = 'users.CustomUser'

EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'

LOGIN_REDIRECT_URL = 'pages:home'
ACCOUNT_LOGOUT_REDIRECT_URL = 'pages:home'

AUTHENTICATION_BACKENDS = (
    "django.contrib.auth.backends.RemoteUserBackend",
    "allauth.account.auth_backends.AuthenticationBackend",
    "django.contrib.auth.backends.ModelBackend",
)

SITE_ID = 1

ACCOUNT_EMAIL_REQUIRED = True
ACCOUNT_USERNAME_REQUIRED = False
ACCOUNT_SIGNUP_FORM_CLASS = "users.forms.CustomUserCreationForm"
ACCOUNT_SIGNUP_PASSWORD_ENTER_TWICE = False
ACCOUNT_SESSION_REMEMBER = True
ACCOUNT_AUTHENTICATION_METHOD = 'email'
ACCOUNT_UNIQUE_EMAIL = True

CRISPY_TEMPLATdE_PACK = 'bootstrap4'


MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'


'''
    --------------------------------------------------
    
    ALL SECURITY CONCERNS MUST BE ADDRESSED BELOW THIS LINE

    --------------------------------------------------
'''
#SECURE_BROWSER_XSS_FILTER = True
#SECURE_CONTENT_TYPE_NOSNIFF = True
#SECURE_HSTS_INCLUDE_SUBDOMAINS = True
#SECURE_SSL_REDIRECT = True
#SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
#SESSION_COOKIE_SECURE = False
#CSRF_COOKIE_SECURE = True
#SECURE_HSTS_SECONDS = 60

#PREPEND_WWW = True
#BASE_URL = "https://###"

#X_FRAME_OPTIONS = 'DENY'
#SECURE_HSTS_PRELOAD = True

wsgi.py

import os

from django.core.wsgi import get_wsgi_application

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'rubillion.settings')

application = get_wsgi_application()

相关的urls.py

from django.urls import path, include, re_path
from .views import *
from rest_framework import routers, renderers


app_name = "pages"
router = routers.DefaultRouter())

urlpatterns = [
    path('', HomePageView.as_view(), name='home'),
]

我如何创建超级用户并检查它们是否存在

(rubyenv)$ python3 manage.py shell
>>> from users.models import CustomUser;
>>> CustomUser.objects.create_superuser('admin', 'a@gmail.com',       '$Admin11')


(rubyenv)$ python3 manage.py shell
>>> from users.models import CustomUser
>>> c = CustomUser.objects.filter(is_superuser=True)
>>> print(c)
<QuerySet [
    <CustomUser: **@gmail.com>, 
    <CustomUser: admin@example.com>, 
    <CustomUser: **@test.com>
    ]>

正在重定向的“我的主页”视图。 我添加了两个打印语句,以验证标头与本地计算机上的标头匹配。

class HomePageView(TemplateView):
    template_name = 'pages/home.html'

    def get(self, request):
        #print(request.headers)
        #print(request.META)
        return render(request, self.template_name, {})

必须取消create_superuser时的错误日志 (无论如何创建用户)

 File "/home/antony/ruby/rubyenv/lib/python3.6/site-packages/django/contrib/auth/models.py", line 162, in create_superuser
    return self._create_user(username, email, password, **extra_fields)
  File "/home/antony/ruby/rubyenv/lib/python3.6/site-packages/django/contrib/auth/models.py", line 145, in _create_user
    user.save(using=self._db)
  File "/home/antony/ruby/rubyenv/lib/python3.6/site-packages/django/contrib/auth/base_user.py", line 66, in save
    super().save(*args, **kwargs)
  File "/home/antony/ruby/rubyenv/lib/python3.6/site-packages/django/db/models/base.py", line 741, in save
    force_update=force_update, update_fields=update_fields)
  File "/home/antony/ruby/rubyenv/lib/python3.6/site-packages/django/db/models/base.py", line 790, in save_base
    update_fields=update_fields, raw=raw, using=using,
  File "/home/antony/ruby/rubyenv/lib/python3.6/site-packages/django/dispatch/dispatcher.py", line 175, in send
    for receiver in self._live_receivers(sender)
  File "/home/antony/ruby/rubyenv/lib/python3.6/site-packages/django/dispatch/dispatcher.py", line 175, in <listcomp>
    for receiver in self._live_receivers(sender)
  File "/home/antony/ruby/authenticated/models.py", line 320, in create_user_profile
    Users.objects.get_or_create(username=instance)
  File "/home/antony/ruby/rubyenv/lib/python3.6/site-packages/django/db/models/manager.py", line 82, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "/home/antony/ruby/rubyenv/lib/python3.6/site-packages/django/db/models/query.py", line 541, in get_or_create
    return self._create_object_from_params(kwargs, params)
  File "/home/antony/ruby/rubyenv/lib/python3.6/site-packages/django/db/models/query.py", line 575, in _create_object_from_params
    obj = self.create(**params)
  File "/home/antony/ruby/rubyenv/lib/python3.6/site-packages/django/db/models/query.py", line 422, in create
    obj.save(force_insert=True, using=self.db)
  File "/home/antony/ruby/rubyenv/lib/python3.6/site-packages/django/db/models/base.py", line 741, in save
    force_update=force_update, update_fields=update_fields)
  File "/home/antony/ruby/rubyenv/lib/python3.6/site-packages/django/db/models/base.py", line 790, in save_base
    update_fields=update_fields, raw=raw, using=using,
  File "/home/antony/ruby/rubyenv/lib/python3.6/site-packages/django/dispatch/dispatcher.py", line 175, in send
    for receiver in self._live_receivers(sender)
  File "/home/antony/ruby/rubyenv/lib/python3.6/site-packages/django/dispatch/dispatcher.py", line 175, in <listcomp>
    for receiver in self._live_receivers(sender)
  File "/home/antony/ruby/exchange/models.py", line 49, in queue_task
    send_task('celerytasks.tasks.volatilityTrader')
  File "/home/antony/ruby/rubyenv/lib/python3.6/site-packages/celery/local.py", line 191, in __call__
    return self._get_current_object()(*a, **kw)
  File "/home/antony/ruby/rubyenv/lib/python3.6/site-packages/celery/app/base.py", line 756, in send_task
    amqp.send_task_message(P, name, message, **options)
  File "/home/antony/ruby/rubyenv/lib/python3.6/site-packages/celery/app/amqp.py", line 552, in send_task_message
    **properties
  File "/home/antony/ruby/rubyenv/lib/python3.6/site-packages/kombu/messaging.py", line 181, in publish
    exchange_name, declare,
  File "/home/antony/ruby/rubyenv/lib/python3.6/site-packages/kombu/connection.py", line 510, in _ensured
    return fun(*args, **kwargs)
  File "/home/antony/ruby/rubyenv/lib/python3.6/site-packages/kombu/messaging.py", line 187, in _publish
    channel = self.channel
  File "/home/antony/ruby/rubyenv/lib/python3.6/site-packages/kombu/messaging.py", line 209, in _get_channel
    channel = self._channel = channel()
  File "/home/antony/ruby/rubyenv/lib/python3.6/site-packages/kombu/utils/functional.py", line 44, in __call__
    value = self.__value__ = self.__contract__()
  File "/home/antony/ruby/rubyenv/lib/python3.6/site-packages/kombu/messaging.py", line 224, in <lambda>
    channel = ChannelPromise(lambda: connection.default_channel)
  File "/home/antony/ruby/rubyenv/lib/python3.6/site-packages/kombu/connection.py", line 852, in default_channel
    self.ensure_connection(**conn_opts)
  File "/home/antony/ruby/rubyenv/lib/python3.6/site-packages/kombu/connection.py", line 422, in ensure_connection
    callback, timeout=timeout)
  File "/home/antony/ruby/rubyenv/lib/python3.6/site-packages/kombu/utils/functional.py", line 355, in retry_over_time
    sleep(1.0)

我遇到了我可以找到的每个堆栈溢出问题,并尝试了每种解决方案的感觉。我已经调试了这个问题4天了,我们迫切需要一些帮助。如果我忘记提供任何信息,请告诉我:)

已解决:
正如Sidnei Pereira指出的那样,问题与芹菜有关。

我没有在远程服务器上设置Rabbitmq 。我在等待首先完成对Gunicorn和Nginx的设置,并且不需要身份验证。在另一个应用程序exchange/models.py

我使用了接收器装饰器,并省略了sender = model_name。当新的价格记录添加到数据库时,我计划运行一个芹菜任务。相反,此事件将在任何记录添加到db时触发

class Price(models.Model):
    ModelField
    ModelField
    objects = models.Manager()

    def __str__(self):
        return self.pair + ' / ' + str(self.timestamp)

    @receiver(post_save)
    def queue_task(instance, created, **kwargs):
        send_task('celerytasks.tasks.volatilityTrader')
        send_task('celerytasks.tasks.swingTrader')

    class Meta:
        managed = False
 

解决方案:

  class Price(models.Model):
    ModelField
    ModelField
    objects = models.Manager()

    def __str__(self):
        return self.pair + ' / ' + str(self.timestamp)

    class Meta:
        managed = False
 
#reciever must go after model is defined and a sender arg is required

@receiver(post_save, sender=Price)
def queue_task(instance, created, **kwargs):
    send_task('celerytasks.tasks.volatilityTrader')
    send_task('celerytasks.tasks.swingTrader')
        

1 个答案:

答案 0 :(得分:1)

通过回溯,我认为您在登录时就将celery用于异步任务。保存User模型时,此celery任务似乎是由Django信号触发的。由于挂起了很长时间,我认为这是因为当您急于向代理发送消息时,消息无法到达。这可能意味着Celery在此远程环境中未正确配置(或根本未配置),或者与其连接的Message Broker(RabbitMQ,Redis,SQS,Kafka等)未运行。

好吧,如果您不了解项目中使用celery的想法(我想是可以的,因为它在INSTALLED_APPS中),就像“在没有在本地环境中运行任何代理的情况下都能正常工作”一样,这意味着某些调试标志将被忽略这-我猜您正在使用的另一个软件包取决于并使用Celery。

一些要调试的东西:

File "/home/antony/ruby/authenticated/models.py", line 320, in create_user_profile
Users.objects.get_or_create(username=instance)

由于Django信号而看起来正在执行

File "/home/antony/ruby/exchange/models.py", line 49, in queue_task
    send_task('celerytasks.tasks.volatilityTrader')

看到了吗?这里一条消息/任务被发送到代理的队列,因此涉及网络连接(除非您使用的是CELERY_TASK_ALWAYS_EAGER),这可能就是服务器永不响应的原因。