Do you have any security concerns with what I've done being implemented in a production web app? Either in the Django HTML Template or my views logic?
I would prefer to have the form in actual html rather than using {{ form }}. Is it ok to allow the user to implement very basic passwords?
views.py is:
from django.shortcuts import render, redirect
from django.contrib.auth import get_user_model
User = get_user_model()
from django.contrib.auth import authenticate, login as auth_login
from django.contrib import auth
from memberships.models import UserMembership
from django.contrib.auth.decorators import login_required
from companies.models import Profile
# Create your views here.
def register(request):
if request.method == "POST":
# User has info and wants an account now!
if request.POST['password1'] == request.POST['password2']:
try:
user = User.objects.get(email=request.POST['email'])
return render(request, 'accounts/register.html', {'error': 'Email has already been taken'})
except User.DoesNotExist:
user = User.objects.create_user(request.POST['email'], password=request.POST['password1'])
auth.login(request, user)
company = Profile()
company.businessperson = request.user
company.first_name = request.POST['firstname']
company.last_name = request.POST['lastname']
company.company_name = request.POST['companyname']
company.phone_number = request.POST['phonenum']
company.save()
return redirect('memberships:payment')
else:
return render(request, 'accounts/register.html', {'error': 'Passwords must match'})
# User wants to enter info
return render(request, 'accounts/register.html')
def login(request):
if request.method == "POST":
user = authenticate(email=request.POST["email"], password=request.POST["password"])
if user is not None:
# Our backend authenticated the credentials
auth_login(request, user)
return redirect('dashboard')
else:
# Backend did not authenticate the credentials
return render(request, 'accounts/login.html', {"error": "Incorrect email and or password"})
else:
return render(request, 'accounts/login.html')
def logout(request):
if request.method == "POST":
auth.logout(request)
return redirect('login')
forms in login.html and register.html:
<!-- login.html -->
<form action="{% url 'login' %}" method="POST">
{% csrf_token %}
<div class="form-group">
<input type="email" name="email" id="exampleInputEmail">
</div>
<div class="form-group">
<input type="password" name="password" id="exampleInputPassword" >
</div>
<input type="submit" value="Login">
</form>
<!-- register.html -->
<form action="{% url 'register' %}" method="POST" >
{% csrf_token %}
<input type="text" name="firstname" id="exampleFirstName" >
<input type="text" name="lastname" id="exampleLastName" >
<input type="text" name="companyname" id="exampleInputCompany" >
<input type="tel" name="phonenum" id="exampleInputPhone" placeholder="Phone Number">
<input type="email" name="email" id="exampleInputEmail" placeholder="Email" required>
<input type="password" name="password1" id="exampleInputPassword" placeholder="Password" required>
<input type="password" name="password2" id="exampleRepeatPassword" placeholder="Repeat Password" required>
<input type="submit" value="Register Account">
</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
recently I am seeing a weird error in my Django application. When I try to sign in, Chrome is stuck on "Processing request". After I click on the login button again it gives me the 403 Forbidden CSRF verification failed error. However, when I click on the Back button and press login again with the same user credentials it logs in successfully. I do not know why this is happening. I have two Django applications which 'home' and 'main', after correct credentials it should take the user to the view of 'home' applications.
My main/user_login.html
<form method="POST" action="{%url 'main:user_login' %}" class="form-signin">
{% csrf_token %}
<div class="form-label-group">
<input type="text" name="username" id="inputText" class="form-control" placeholder="Username" required autofocus>
<br/>
</div>
<div class="form-label-group">
<input type="password" name="password" id="inputPassword" class="form-control" placeholder="Password" required>
</div>
<div class="custom-control custom-checkbox mb-3">
<input type="checkbox" class="custom-control-input" id="customCheck1">
<label class="custom-control-label" for="customCheck1">Remember password</label>
</div>
<input type="submit" class="form-control" name="" value="Login">
<hr class="my-4">
<p>Don't have account? Sign up here</p>
{% if message %}<p style="color: red;">{{ message }}</p>{% endif %}
Forgot Password
</form>
my main/views.py:
def user_login(request):
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:
login(request,user)
messages.info(request, "Successfully signed in")
return redirect(reverse('home:home'))
else:
message = 'Sorry, the username or password you entered is not valid please try again.'
return render(request, 'home/user_login.html', {'message':message})
else:
message = 'Sorry, the username or password you entered is not valid please try again.'
return render(request, 'home/user_login.html', {'message':message})
else:
form=AuthenticationForm()
return render(request, 'home/user_login.html', {"form":form})
my home/views.py:
#login_required
def home(request):
context = {
'posts': Post.objects.all()
}
return render(request, 'home/home.html', context)
I do not understand what is causing the issue which as I mentioned before after going back and clicking on login again the user can successfully login.
Thanks in advance!
Edit: I have realized what causes the error it is the else statement that throws the error message. I have changed my view right now it does not give me an error but I have to click on the login button twice else it would get stuck again. My view is now:
def user_login(request):
if request.method == 'POST':
username = request.POST.get('username', '')
password = request.POST.get('password', '')
user = authenticate(request, username=username, password=password)
if user is not None:
return redirect('home:home')
else:
messages.error(request,'Sorry, the username or password you entered is not valid please try again.')
return HttpResponseRedirect('/')
else:
form=AuthenticationForm()
return render(request, 'main/user_login.html', {"form":form})
And my user_login.html is now:
<form method="POST" action="{% url 'main:user_login' %}" class="form-signin">
{% csrf_token %}
<div class="form-label-group">
<input type="text" name="username" id="inputText" class="form-control" placeholder="Username" required autofocus>
<br/>
</div>
<div class="form-label-group">
<input type="password" name="password" id="inputPassword" class="form-control" placeholder="Password" required>
</div>
<div class="custom-control custom-checkbox mb-3">
<input type="checkbox" class="custom-control-input" id="customCheck1">
<label class="custom-control-label" for="customCheck1">Remember password</label>
</div>
<input type="submit" class="form-control" name="" value="Login">
<hr class="my-4">
<p>Don't have account? Sign up here</p>
{% for message in messages %}
<p style="color: red;">{{ message }}</p>
{% endfor %}
Forgot Password
</form>
This is causing the issue:
else:
messages.error(request,'Sorry, the username or password you entered is not valid please try again.')
return HttpResponseRedirect('/')
Try this one:
#login_required
def home(request):
post = Post.objects.all()
context = {'post':post}
return render(request, 'home/home.html', context)
I think the problem might be in else block.
Just try this one:
def user_login(request):
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:
login(request,user)
messages.info(request, "Successfully signed in")
return redirect(reverse('home:home'))
else:
message = 'Sorry, the username or password you entered is not valid please try again.'
return render(request, 'home/user_login.html', {'message':message})
else:
form=AuthenticationForm()
return render(request, 'home/user_login.html', {"form":form})
Django's built-in tags need spaces
fix this in your form: action="{% url 'main:user_login' %}"
I am using a custom user model for my Django project and I can log in via /admin/ perfectly fine. But when I go to /accounts/login and try to log in, it just bounces me back to the login page without logging in. I am using django-registration-redux with the simple backend.
Via logging I discovered that the error happens in this method in django.contrib.auth.__init__.py:
def get_user(request):
"""
Returns the user model instance associated with the given request session.
If no user is retrieved an instance of `AnonymousUser` is returned.
"""
from .models import AnonymousUser
user = None
try:
#
# EXCEPTION THROWN ON BELOW LINE
#
user_id = _get_user_session_key(request)
backend_path = request.session[BACKEND_SESSION_KEY]
except KeyError:
pass
else:
if backend_path in settings.AUTHENTICATION_BACKENDS:
backend = load_backend(backend_path)
user = backend.get_user(user_id)
# Verify the session
if hasattr(user, 'get_session_auth_hash'):
session_hash = request.session.get(HASH_SESSION_KEY)
session_hash_verified = session_hash and constant_time_compare(
session_hash,
user.get_session_auth_hash()
)
if not session_hash_verified:
request.session.flush()
user = None
return user or AnonymousUser()
Any ideas? /accounts/register/ performs as expected, although I have overridden RegistrationView. Perhaps I have to do the same thing for logging in?
Login.html
{% extends "base.html" %}
{% load staticfiles %}
{% block body_block %}
<link href="{% static 'css/signin.css' %}" rel="stylesheet">
<div class="container">
<div class="jumbotron">
<h1 class="display-3" align="center">Login</h1>
</div>
<form method="post" action=".">
{% csrf_token %}
<h2 class="form-signin-heading">Please sign in</h2>
<label for="inputEmail" class="sr-only">Username</label>
<input type="text" name="email" id="id+username" class="form-control" placeholder="Username" required autofocus>
<label for="inputPassword" class="sr-only">Password</label>
<input type="password" name="password" id="id_password" class="form-control" placeholder="Password" required>
<button class="btn btn-lg btn-primary btn-block" type="submit" value="Submit">Login</button>
</form>
Not a member?
Register
</div>
<p>
</p>
{% endblock %}
Urls.py
class MyRegistrationView(RegistrationView):
success_url = '/'
form_class = UserProfileRegistrationForm
def get(self, request, *args, **kwargs):
form = self.form_class(initial=self.initial)
return render(request, self.template_name, {'form': form})
def register(self, form):
logging.debug("THIS IS MY REGISTER")
new_user = form.save(commit=False)
new_user.set_password(form.cleaned_data['password1'])
new_user.save()
login(self.request, new_user)
logging.debug("Logged in")
signals.user_registered.send(sender=self.__class__,
user=new_user,
request=self.request)
logging.debug("After signals")
return new_user
urlpatterns = [
url(r'^', include('base.urls')),
url(r'^admin/', admin.site.urls),
url(r'^accounts/register/$', MyRegistrationView.as_view(), name="registration_register"),
url(r'^accounts/password/change/$', MyRegistrationView.as_view(), name="auth_password_change"),
url(r'^accounts/password/change/done/$', MyRegistrationView.as_view(), name="auth_password_changed"),
url(r'^accounts/', include('registration.backends.simple.urls')),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
EDIT:
I have a temporary fix of throwing a view into login in urls.py. Something tells me this is extremely dirty but it seems to work... for now. I'm open to better alternatives.
url(r'^accounts/login/$', my_view, name="login"),
def my_view(request):
if request.POST:
username = request.POST['email']
password = request.POST['password']
user = authenticate(username=username, password=password)
if user is not None:
login(request, user)
return render(request, 'index.html', {})
# Redirect to a success page.
else:
# Return an 'invalid login' error message.
pass
else:
return render(request, 'registration/login.html', {})
Try using {{ form }} in your login template, instead of rendering the fields manually. This can show whether the problem is in your template or elsewhere.
In this case, I think that the form fields should be username and password, not email and password as you have.
<input type="text" name="username" id="id_username" class="form-control" placeholder="Username" required autofocus>
<input type="password" name="password" id="id_password" class="form-control" placeholder="Password" required>
my template is below:
<div id="divLogin">
{% block login %}
<form action="/login" method="post">
{% csrf_token %}
<label for="id_name"></label><input type="text" name="email" id="id_name" placeholder="Your Email">
<label for="id_pass"></label><input type="password" name="password" placeholder="Your Password">
<input type="submit" id="btnLogin" value="Log In" class="btn">
</form>
{% endblock %}
</div>
I have already add {% csrf_token %} in template, and my login view is
def login_view(request):
if request.method == 'POST':
useremail=request.POST['email']
password=request.POST['password']
try:
user=User.objects.get(email=useremail)
if user.check_password(password):
uAuth=authenticate(username=user.username,password=password)
login(request,uAuth)
return render_to_response("blog.html",{'loginuser':user},context_instance=RequestContext(request))
except User.DoesNotExist:
return redirect('/')
return redirect('/')
Even i used render_to_response and RequestContext i still got error.
there is one thing very wired, i put a breakpoint to login_view method, but csrf error point out before it go into login_view methond. so there is no response about this method?
Is there anything wrong about my code?
I have add django.middleware.csrf.CsrfViewMiddleware in MIDDLEWARE_CLASSES in my settings.py.
You must use redirect after post.
Redirect to a view that renders your template.
def login_view(request):
if request.method == 'POST':
useremail=request.POST['email']
password=request.POST['password']
try:
user=User.objects.get(email=useremail)
if user.check_password(password):
uAuth=authenticate(username=user.username,password=password)
login(request,uAuth)
return HttpResponseRedirect('/someurl')
except User.DoesNotExist:
return redirect('/')
else:
return render_to_response('login.html',context_instance=RequestContext(request))
def someurl(request):
if request.method == 'GET':
render_to_response("blog.html",
{'loginuser':user},context_instance=RequestContext(request))
As of now, I have my registration form and my log in form on two different pages, I can't seem to put them in one view because the way I did it, the views require different return statements. So here is my registration view function:
def register_user(request):
if request.method == 'POST':
form = MyRegistrationForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect('/accounts/register_success')
args = {}
args.update(csrf(request))
args['form'] = MyRegistrationForm()
return render_to_response('register.html', args)
def register_success(request):
return render_to_response('register_success.html')
and here is my log in and authentication view:
def login(request):
c = {}
c.update(csrf(request))
return render_to_response('login.html', c)
def auth_view(request):
username = request.POST.get('username', '')
password = request.POST.get('password', '')
user = auth.authenticate(username=username, password=password)
if user is not None:
auth.login(request, user)
return HttpResponseRedirect('/accounts/loggedin')
else:
return HttpResponseRedirect('/accounts/invalid')
Here is the template for the log in page:
<form action="/accounts/auth/" method="post">{% csrf_token %}
<label for="username">User name:</label>
<input type="text" name="username" value="" id="username">
<label for="password">Password:</label>
<input type="password" name="password" value="" id="password">
<input type="submit" value="login" />
</form>
and here is the template for the registration page:
<h2>Register</h2>
<form action="/accounts/register/" method="post">{% csrf_token %}
{{form}}
<input type="submit" value="Register" />
</form>
Again, I can't seem to put them together because the views have to return different things.. any idea on how to do it?
EDIT: This is my urls.py:
url(r'^admin/', include(admin.site.urls)),
url(r'^$', index),
url(r'^accounts/auth/$', auth_view),
url(r'^invalid/$', invalid_login),
url(r'^accounts/register/$', register_user),
url(r'^accounts/register_success/$', register_success),
so it will only use the register_user view if the url is accounts/register, I want it to user the register_view view if it is the homepage (^$). My index view is this:
def index(request):
c = {}
c.update(csrf(request))
return render_to_response('index.html', c)
it basically just adds a csrf token to my index.html (log in template, as seen above). This is why I want to be able to somehow merge index and the register_user view, since register_user view calls the actual form = MyRegistrationForm(request.POST) which is used in the registration template (the registration template uses {{form}}
If you just want to show login and registration on the same page. Create a html page with two forms. Action of one of them to url '/accounts/register/' and another one to '/accounts/auth/'.
for example, change your register.html to:
<html>
<head><body>
<form action="/accounts/auth/" method="post">{% csrf_token %}
<label for="username">User name:</label>
<input type="text" name="username" value="" id="username">
<label for="password">Password:</label>
<input type="password" name="password" value="" id="password">
<input type="submit" value="login" />
</form>
<h2>Register</h2>
<form action="/accounts/register/" method="post">{% csrf_token %}
{{form}}
<input type="submit" value="Register" />
</form>
</body>
</html>
When submit the form, it will go to corresponding view and redirect based on that view.
EDIT:To pass a MyRegistrationForm instance you can update the index view as follows:
def index(request):
c = {}
c.update(csrf(request))
c.update({'form':MyRegistrationForm()})
return render_to_response('index.html', c)
use the login.html as above html code in the answer.
You can do this with a help of little Javascript. Let's create a input field first:
<input type="hidden" name="button-name" id="button-name" value="" />
<input type="submit" name="register-button" id="register-button" onclick="changeValue()" />
function changeValue(){
document.getElementById('button-name').value="register"
}
Now, in your views do this:
button_name = request.POST['button-name']
if button-name=='register':
# Do the registration
# Redirect to another view or template
else:
# Do your login thing
# Redirect where you want