Django различает неправильную информацию для входа и неактивного пользователя при входе в систему
В настоящее время я добавил на свой сайт метод подтверждения электронной почты при регистрации. Однако я заметил, что когда пользователь зарегистрирован, но еще не нажал на ссылку подтверждения и пытается войти, я не могу отличить неправильного пользователя/пароль от неподтвержденного пользователя.
Это моя функция входа в систему:
def loginUser(request):
if request.user.is_authenticated:
return redirect("decks:index")
if request.method == "POST":
form = AuthenticationForm(request, data=request.POST)
if form.is_valid():
username = form.cleaned_data.get('username')
password = form.cleaned_data.get('password')
user = authenticate(username=username, password=password)
if user is not None and user.is_active:
login(request, user)
return redirect("myApp:portal")
elif user is not None:
messages.error(request, "Email is not confirmed.")
else:
messages.error(request, "Invalid username or password.")
else:
messages.error(request, "Invalid username or password.")
form = AuthenticationForm()
return render(request, "myApp/login.html", context = {'login_form': form})
Проблема в том, что при запуске form.is_valid() выполняется authenticate функция из /home/nowork/.local/lib/python3.8/site-packages/django/contrib/auth ModelBackend:
def authenticate(self, request, username=None, password=None, **kwargs):
if username is None:
username = kwargs.get(UserModel.USERNAME_FIELD)
if username is None or password is None:
return
try:
user = UserModel._default_manager.get_by_natural_key(username)
except UserModel.DoesNotExist:
# Run the default password hasher once to reduce the timing
# difference between an existing and a nonexistent user (#20760).
UserModel().set_password(password)
else:
if user.check_password(password) and self.user_can_authenticate(user):
return user
Таким образом, form.is_valid() никогда не будет истиной, если флаг is_active установлен False. Поэтому у меня нет способа определить, является ли комбинация пользователь+пароль неправильной или пользователь еще не подтвержден.
Я не уверен, что это правильный способ сделать это, я думал сделать что-то вроде:
User.objects.get(username=request.POST['username'])
Могут ли пользователи как-то использовать это? Есть ли лучший способ сделать это?
Использую python3 и Django 4.0
Вы можете сделать свой собственный CustomLoginBackend как
from django.contrib.auth import get_user_model
class CustomLoginBackend(object):
def authenticate(self, request, username, password):
User = get_user_model()
try:
user = User.objects.using(db_name).get(username=username)
except User.DoesNotExist:
return None
else:
if user.check_password(password):
return user
return None
Тогда в вашем views.py
def loginUser(request):
if request.user.is_authenticated:
return redirect("decks:index")
if request.method == "POST":
form = AuthenticationForm(request, data=request.POST)
if form.is_valid():
username = form.cleaned_data.get('username')
password = form.cleaned_data.get('password')
user = authenticate(username=username, password=password)
if user is not None:
if user.is_active == True:
login(request, user)
return redirect("myApp:portal")
else:
messages.error(request, "Email is not confirmed.")
else:
messages.error(request, "Invalid username or password.")
else:
messages.error(request, "Invalid username or password.")
form = AuthenticationForm()
return render(request, "myApp/login.html", context = {'login_form': form})
И, наконец, не забудьте добавить AUTHENTICATION_BACKENDS в свой settings.py в качестве
AUTHENTICATION_BACKENDS = ['path_to_your.CustomLoginBackend ',]