I've built a "firewall" login form that I want to put in front of my
actual production website while I develop the site. The idea is to try
and keep the "bad guys" out of the site and at the same time see what
usernames and passwords they're using. The problem I'm having is that
if I enter an invalid username/password pair, my form's error message
doesn't get displayed. I realize that for my purposes, it it might be
better to not display any error message at all but I'd still like to
understand what the problem is. Can anyone see what I'm doing wrong?
Thanks.
# views.py
import logging
logger = logging.getLogger(__name__)
from django.contrib.auth import authenticate
from django.contrib.auth.forms import AuthenticationForm
from django.contrib.auth.views import login
from django.http import HttpResponseRedirect
def firewall_login(request, *args, **kwargs):
if request.method == "POST":
form = AuthenticationForm(request, data=request.POST)
username = request.POST['username']
password = request.POST['password']
if form.is_valid():
fw_username = form.cleaned_data['username']
fw_password = form.cleaned_data['password']
user = authenticate(username=fw_username, password=fw_password)
if user is not None:
if user.is_active:
login(request, user)
logger.info("User '%s' logged in." % fw_username)
return HttpResponseRedirect("/accounts/profile/")
else:
logger.info("User '%s' tried to log in to disabled account." % fw_username)
return HttpResponseRedirect("/accounts/disabled/")
else:
logger.info("User '%s' tried to log in with password '%s'." % (username, password))
form = AuthenticationForm(request) # Display bound form
else:
form = AuthenticationForm() # Display unbound form
return render(request, "registration/login.html", {"form": form,})
# login.html
{% extends "base.html" %}
{% block content %}
{% if form.errors %}
<p class="alert alert-error">Sorry, that's not a valid username or password</p>
{% endif %}
{% if form.errors %}
{% for field in form %}
{% for error in field.errors %}
<div class="alert alert-error">
<strong>{{ error|escape }}</strong>
</div>
{% endfor %}
{% endfor %}
{% for field in form.non_field_errors %}
<div class="alert alert-error">
<strong>{{ error|escape }}</strong>
</div>
{% endfor %}
{% endif %}
<form action="" method="post">
{% csrf_token %}
<p><label for="username">Username:</label>{{ form.username }}</p>
<p><label for="password">Password:</label>{{ form.password }}</p>
<input type="hidden" name="next" value="{{ next|escape }}" />
<input class="btn btn-primary" type="submit" value="login" />
</form>
{% endblock %}
It's because you pass new form instance. Validation occurs on is_valid call.
So, just remove form = AuthenticationForm(request) in else block:
def firewall_login(request, *args, **kwargs):
if request.method == "POST":
form = AuthenticationForm(request, data=request.POST)
username = request.POST['username']
password = request.POST['password']
if form.is_valid():
fw_username = form.cleaned_data['username']
fw_password = form.cleaned_data['password']
user = authenticate(username=fw_username, password=fw_password)
if user is not None:
if user.is_active:
login(request, user)
logger.info("User '%s' logged in." % fw_username)
return HttpResponseRedirect("/accounts/profile/")
else:
logger.info("User '%s' tried to log in to disabled account." % fw_username)
return HttpResponseRedirect("/accounts/disabled/")
else:
logger.info("User '%s' tried to log in with password '%s'." % (username, password))
else:
form = AuthenticationForm() # Display unbound form
return render(request, "registration/login.html", {"form": form,})
Related
here is my loginHtml code
<form method="post" action="handleLogin_url" enctype="multipart/form-data">
{{ tryAgain }}
<br>
{% csrf_token %}
<label for="username">Enter Username</label><input id="username" name="username" type="text">
<label for="password">Enter password</label><input id='password' name="password" type="password">
<input type="submit" value="Lets Go">
views.py
def handleLogin(HttpRequest):
if HttpRequest.method=='POST':
enteredname = HttpRequest.POST['username']
# user = User.objects.get(username=enteredname)
enteredpassword = HttpRequest.POST['password']
user = authenticate( HttpRequest, username=enteredname,password=enteredpassword)
# return render(HttpRequest, 'seeData.html',
# {'User': user, 'enteredname': enteredname, 'enteredpassword': enteredpassword})
if user is not None:
return render(HttpRequest, 'seeData.html', {'Users':user, 'enteredname':enteredname, 'enteredpassword':enteredpassword})
else :
tryAgain = "Invalid username or password try again"
return render(HttpRequest, 'LoginHtml.html', {'tryAgain':tryAgain})
else:
return render(HttpRequest,'LoginHtml.html')
seeDataHtml code
{{ User.username }},{{ User.password }}||{{ enteredname }} {{ enteredpassword }}
when I try using superuser credentials a superuser object is returned but when I use a user credential no object is returned but when I log into admin site I can see user objects
You doing here a lot of mistakes first thing your HTML should look like this:
<div class="container py-5">
<form method="POST" enctype="multipart/form-data">
<div class="mb-3">
{% csrf_token %}
{{login_form}}
</div>
<input type="submit" name="Log in" class="btn btn-primary"></input>
</form>
{% for message in messages %}
{% if message.tags %}
<span class="{{ message.tags }}"> </span>
{{ message }}
{% endif %}
{% endfor %}
<br>
Forgot Password
</div>
In views.py
from django.contrib.auth.forms import AuthenticationForm
from django.contrib.auth import login as login_auth, authenticate
from django.contrib import messages
from django.shortcuts import redirect, render
def login(request):
if request.user.is_authenticated: #to check if user is authenticated
return redirect('home')
if request.method == "POST":
form = AuthenticationForm(request, data=request.POST)
if form.is_valid(): #If form is valid returns True
username = form.cleaned_data.get('username')
password = form.cleaned_data.get('password')
user = authenticate(username=username, password=password)
if user is not None:
login_auth(request, user)
return redirect('home')
else:
messages.error(request,"Invalid username or password.")
else:
messages.error(request,"Invalid username or password.")
else:
form = AuthenticationForm()
return render(request, 'login.html', {'login_form': form})
Also, I saw that you create a new page to show a message error you can do that using Django messages from django.contrib import messages
error messages are not working in Django templates.
after add error code in html template it shows no error message in webapp when fields are empty and press on submit button. html5 error is "novalidate" in template.
ValueError at /signup/
The view blog.views.user_signup didn't return an HttpResponse object. It returned None instead.
forms.py
from django import forms
from django.contrib.auth.forms import UserCreationForm, AuthenticationForm, UsernameField
from django.contrib.auth.models import User
from django.utils.translation import gettext,gettext_lazy as _
class SignUpForm(UserCreationForm):
password1 = forms.CharField(label='Password',widget=forms.PasswordInput(attrs={'class':'form-control'}))
password2 = forms.CharField(label='Confirm Password(again)',widget=forms.PasswordInput(attrs={'class':'form-control'}))
class Meta:
model = User
fields = ['username','first_name','last_name','email']
labels = {'username':'Username','first_name':'First Name','last_name':'Last Name','email':'Email'}
widgets = {'username':forms.TextInput(attrs={'class':'form-control'}),
'first_name':forms.TextInput(attrs={'class':'form-control'}),
'last_name':forms.TextInput(attrs={'class':'form-control'}),
'email':forms.EmailInput(attrs={'class':'form-control'}),}
class LoginForm(AuthenticationForm):
username = UsernameField(widget=forms.TextInput(attrs={'autofocus':True, 'class':'form-control'}))
password = forms.CharField(label=_('password'),strip=False, widget=forms.PasswordInput(attrs={'autocomplete':'current-password','class':'form-control'}))
signup.html
{% extends 'blog/base.html' %}
{% load static %}
{% block content %}
<div class="col-sm-10">
<h3 class="text-white my-5">Signup Page</h3>
<form action="" class="post" novalidate>
{% csrf_token %}
{% for fm in form %}
<div class="form-group">
{{fm.label_tag}} {{fm}} {{fm.errors | striptags}}
</div>
{% endfor %}
<input type="submit" value='Submit' class='btn btn-primary'>
{% if form.non_field_errors %}
{% for error in form.non_field_errors %}
<p> {{error}} </p>
{% endfor %}
{% endif %}
</form>
</div>
{% endblock content %}
views.py
from django.shortcuts import render,HttpResponseRedirect
from django.contrib import messages
# Create your views here.
# home
def home(request):
return render(request, 'blog/home.html')
# about
def about(request):
return render(request, 'blog/about.html')
# contact
def contact(request):
return render(request, 'blog/contact.html')
# Dashboard
def dashboard(request):
return render(request, 'blog/dashboard.html')
# Logout
def user_logout(request):
return HttpResponseRedirect('/')
# Signup
def user_signup(request):
if request.method == 'POST':
form = SignUpForm(request.POST)
if form.is_valid():
messages.success(request, 'Congratulations You have become an Author.')
form.save()
else:
form = SignUpForm()
return render(request, 'blog/signup.html',{'form':form})
# Login
def user_login(request):
form = LoginForm()
return render(request, 'blog/login.html', {'form':form})
You need to handle GET and POST request :
def user_signup(request):
if request.method == 'POST':
form = SignUpForm(request.POST)
if form.is_valid():
messages.success(request, 'Congratulations You have become an Author.')
form.save()
else:
form = SignUpForm()
return render(request, 'blog/signup.html',{'form':form})
Please make sure to use POST method in your html :
<form action="" method="POST" class="post" novalidate>
...
</form>
I have a class based view which shows a login-form.
The problem is that I can't display error messages. I am trying to send an error message in a parameter in the URL to display it inside the HTML template file. But it does not work.
Here is my code so far:
forms.py
# a class which act as a view - it displays the login-form
class LoginForm(AuthenticationForm, BaseLoginView):
username=forms.CharField(widget=forms.TextInput(attrs={'class':'form-control'}))
password=forms.CharField(widget=forms.PasswordInput(attrs={'class':'form-control'}))
def get_context_data(self, **kwargs):
context = super(LoginForm, self).get_context_data(**kwargs)
context['error'] = ''
return context
urls.py
urlpatterns = [
path('login/', views_auth.LoginView.as_view(form_class=LoginForm, redirect_authenticated_user=True), name='login'), # login-page
]
views.py
# login functionality for the user
def custom_user_login(request):
if request.method == 'GET':
error_message = ''
return redirect('home')
elif request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
error_message = ''
# if the username & password is correct
user = authenticate(request, username=username, password=password)
if user is not None:
# Redirecting to the required login according to user type (admin / regular-user)
if user.is_superuser or user.is_staff:
login(request, user)
return redirect('admin_section/')
else:
login(request, user)
return redirect('/')
# display error message
else:
base_url = reverse('login') # /login/
query_string = urlencode({'error': 'The username & password combination are incorrect - please try again!'}) # error=The username & password combination are incorrect - please try again!
url = '{}?{}'.format(base_url, query_string) # /login/?error=The username & password combination are incorrect - please try again!
return redirect(url) # redirects to the login page with an error-message
login.html
<!-- error message -->
<div id="error" class="alert alert-danger alert-dismissible" role="alert">
×
{{ view.error }}
</div>
<form method="post" action="{% url 'custom_login' %}">
{% csrf_token %}
{% for field in form %}
<div class="form-group row">
{{ field.errors }}
<label for="{{ field.name }}" class="col-md-4 col-form-label text-md-right">{{ field.label }}</label>
<div class="col-md-6">
{{ field }}
</div>
</div>
{% endfor %}
<div class="col-md-6 offset-md-4">
<button type="submit" class="btn btn-primary">
Login
</button>
</div>
</form>
You don't need to manually collect, add to context, and display errors. The form itself stores the errors. You're already getting field-specific errors with your call to field.errors in the template, but you can also get non-field-specific errors with form.errors. See the Django docs on form errors for more details.
As an aside, you can display GET variables from the url in your templates. Simply use {{ request.GET.error }}. Again, there is no need to encode your error message in the url itself. It's not a good way to solve this problem, which Django has already solved for you.
I'm creating an app in which I'd like to use my own custom login form with a captcha field. My intention is to do this without using an external library (except for requests) but I couldn't add captcha field to my custom form in forms.py, so I added it directly to login.html but for some reason when I do form.is_valid() it returns an error.
I've already seen the solutions in Django - adding google recaptcha v2 to login form and Adding a Recaptcha form to my Django login page but as I said, I'd like to do this without using an external library.
views.py
...
def login_view(request):
if request.method == 'POST':
form = CustomLoginForm(request.POST)
result = is_recaptcha_valid(request)
print(result) # prints True
if form.is_valid():
username = form.cleaned_data['username']
email = form.cleaned_data['email']
password = form.cleaned_data['password']
user = authenticate(request, username=username, password=password)
if user is not None:
login(request, user)
# Redirect to index
messages.success(request, "Logged in.")
return HttpResponseRedirect(reverse('orders:index'))
else:
messages.error(request, "Invalid credentials.")
else:
print("error")
return render(request, 'registration/login.html', {'form': CustomLoginForm()})
else:
form = CustomLoginForm()
return render(request, 'registration/login.html', {'form': form})
forms.py
class CustomLoginForm(AuthenticationForm):
email = forms.EmailField(
error_messages={
'required': 'Please enter your email.',
'invalid': 'Enter a valid email address.'
},
help_text='Email',
)
login.html
<form class="" action="{% url 'orders:login' %}" method="post">
{% csrf_token %}
{% for field in form %}
<p>
{{ field.label_tag }}<br>
{{ field }}
{% if field.help_text %}
<small style="color: grey">{{ field.help_text }}</small>
{% endif %}
{% for error in field.errors %}
<p style="color: red">{{ error }}</p>
{% endfor %}
</p>
{% endfor %}
<!-- ReCAPTCHAV3 -->
<script src="https://www.google.com/recaptcha/api.js" async defer></script>
<div class="g-recaptcha" data-sitekey='key-here'></div>
<button class="btn btn-success" type="submit" name="">Login</button>
<!-- <input type="hidden" name="next" value="{{ next }}"> -->
</form>
is_recaptcha_valid() function already returns True so I didn't share that. I'm a beginner in Django, so if you can please explain in two words what I've done wrong instead of just posting the answer, I'd be grateful. Thank you for your time.
The AuthenticationForm is slightly different than the others..
If your check AuthenticationForm class, AuthenticationForm 's first arguments is not data like others form:
class AuthenticationForm(forms.Form):
...
def __init__(self, request=None, *args, **kwargs):
...
Thats why you need to pass request.POST to data.
So update your code like this:
def login_view(request):
if request.method == 'POST':
form = CustomLoginForm(data=request.POST)
...
hi i have a problem with login function in django ,when i loggin succes see when user is logged but main.html didnot .
wiews
def user_login(request):
context = {}
if request.method == "POST":
username = request.POST['username']
password = request.POST["password"]
user = authenticate(request,username=username,password=password)
if user.is_authenticated:
print("1")
login(request, user)
if request.GET.get('next',None):
print("2")
return HttpResponseRedirect(request.GET['next'])
return HttpResponseRedirect(reverse('success'))
else:
print("3")
context["error"] = "nieprawidlowe dane"
return render(request,'auth/login.html',context)
else:
print("4")
return render(request,'auth/login.html',context)
#login_required(login_url="/login/")
def success(request):
c = {}
c['user'] = request.user
return render(request,'auth/success.html',c)
and in here is succes and on this page django can see when user is logged
{% extends 'main.html' %}
{% block article %}
<p>User <b>{{ user.username }}</b> jestes zalogowony</p>
<form method="post" action="/logout/">
{% csrf_token %}
<input type="submit" value="Logout">
</form>
{% endblock %}
but main.html didnot see user