Несмотря на вызов функции authenticate и login для ввода правильной комбинации имени пользователя и пароля, при переходе в другое представление сеанс не может связаться с моделью пользователя.Вместо этого модель является «AnonymousUser», и они не могут прогрессировать, потому что требуется, чтобы они были действительным пользователем входа в систему.
У меня была система, которая работала хорошо в течение достаточно долгого времени (как я полагаю, все говорят, прежде чем у них возникнут проблемы ...) Чтобы избежать необходимости добавлять декоратор require_login к каждому представлению, у меня естьсоздал промежуточное программное обеспечение, которое проверяет, что пользователь является логином, и должно перенаправить его, если это не так, на страницу входа в систему.
Эта настройка работала в течение некоторого времени, но недавние изменения в модели пользователя показали, чтопользователи, которые присутствовали перед миграцией, больше не могут войти в систему. Что сбивает с толку то, что, если их пароли обновляются через администратора django, они могут затем получить доступ к сайту как обычный
вид аутентификации
import django.http
from django.shortcuts import render, redirect
from django.contrib.auth import authenticate, login, logout, update_session_auth_hash, models as admin_models
from django.conf import settings
from .models import LoginAttempts
import logging
logging.basicConfig(level=logging.DEBUG)
log = logging.getLogger(__name__)
# Define the alert to be given to the users if they have passed invalid user credentials
INVALID_LOGIN = {
...
}
LOCKED_ACCOUNT = {
...
}
def login_form(request):
""" Return the login page """
if request.POST: # Handle the form submission
# Extract the user information + attempt to authenticate the user
username, password = request.POST.get("username"), request.POST.get("password")
log.debug("user '{}' attempting to log in".format(username))
# Collect the user account corresponding to the username passed
accountQuery = admin_models.User.objects.filter(username=username)
if accountQuery.exists() and password is not None:
userModel = accountQuery.first()
if userModel.loginattempts.isLocked:
log.debug("'{}'s' account has been locked due to repeated failed attempts".format(username))
request.session["alerts"].append(LOCKED_ACCOUNT)
return render(request, "login.html")
else:
log.debug("'{}'s username doesn't exist or no password provided".format(username))
request.session["alerts"].append(INVALID_LOGIN)
return render(request, "login.html")
# Authenticate the user/password combination
user = authenticate(request, username=username, password=password)
if user is not None: # The user has been authenticated, log them in and redirect to the index page
log.debug("User {} has been verified - logging user in".format(username))
login(request, user)
userModel.loginattempts.attempts = 0
userModel.save()
return django.http.HttpResponseRedirect("/")
else:
log.debug("User {} failed to authenticate".format(username))
request.session["alerts"].append(INVALID_LOGIN)
userModel.loginattempts.attempts += 1
if userModel.loginattempts.attempts >= 10: userModel.loginattempts.isLocked = True
userModel.save()
return render(request, "login.html")
Промежуточное программное обеспечение
class RequireLogin:
""" Require that the user be logging in to view the pages - avoiding the requirement
to declare "@login_required" on all views
"""
def __init__(self, get_response: callable):
self.get_response = get_response # Function passes the request through and fulfils and collects the generates response
def __call__(self, request):
if request.path_info != settings.LOGIN_URL and not request.user.is_authenticated:
return HttpResponseRedirect(settings.LOGIN_URL)
return self.get_response(request)
Журналы
Если в операторе if промежуточного программного обеспечения мы добавляем операторы print для печати первого условия (которое, я знаю, должно быть истинным...) запрос, пользовательская модель запроса, пользовательская модель запроса is_authenticated.мы получаем следующую реакцию от сервера:
Очевидно, что функция определила, что пользователь может войти в систему, и они перенаправляются на страницу индекса, однако, когда онизапросить страницу индекса, они не идентифицированы как авторизованные сеансом и перенаправлены обратно.
Вот изображение маркеров сеанса Django, при попытке войти в систему для одного пользователя он действительно обновляет толькоодна строка:
Чтобы ответить Даниэлю, вот список промежуточного программного обеспечения в их порядке:
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',
"ace_main.middleware.RequireLogin",
"ace_main.middleware.RestrictedAccessZones", # For certain areas - extra restriction - don't worry about this
"ace_main.middleware.RemoveAlerts", # Alert structure dequeue alerts already shown to the user
"ace_main.middleware.UserLogging", # track the user around the site
]