Reputation:
I'm experimenting with Django and I tried to create a login/register application. Here's where I've stuck - I'm able to register users, but then I can't login with them. Here's the code I think is relevant:
views.py
def login(request, template='accounts/sign_in.html'):
if request.user.is_authenticated():
return redirect(reverse('games'))
if request.method == 'POST':
post = request.POST.copy()
if 'password' in post:
post['password'] = make_password(post['password'])
form = AuthenticationForm(data=post)
if form.is_valid():
login(request, form.get_user())
messages.success(
request, "Successfully logged in.", extra_tags='success')
return redirect(reverse('games'))
else:
messages.warning(
request, "Wrong username or password." + request.POST['username'] + " " + request.POST['password'], extra_tags='error')
return redirect(reverse('login'))
return views.login(request, template)
def register(request, template='accounts/sign_up.html'):
if request.user.is_authenticated():
return redirect(reverse('home'))
if request.method == 'POST':
form = RegisterForm(request.POST)
if form.is_valid():
new_user = User(
username=form.cleaned_data['username'],
password=make_password(form.cleaned_data['password1']),
is_active=True,
)
new_user.save()
messages.success(request, "Your account was successfully created.")
return redirect(reverse('games'))
else:
form = RegisterForm()
return render(request, template, {'register_form': form})
When I try to log in with a user I've created (username: qwe, password: qweqweqwe), I get redjrected to login again, but the exact same username and password are printed in the message:
Wrong username or password.qwe qweqweqwe
However, when I try the interactive shell, here's what I get:
>>> User.objects.all()
[<User: admin>, <User: asd>, <User: qwe>]
>>> User.objects.all()[2]
<User: qwe>
>>> User.objects.all()[2].password
u'pbkdf2_sha256$10000$HM2k6uDntJ68$DLqHKcGxtJG7pJC7tbZcm29vB88LEgaw2xroqZEkTFw='
So I have such a user and it's a valid account.
Upvotes: 0
Views: 2558
Reputation: 137290
login()
This is probably the problem:
login(request, form.get_user())
You already have a login
function and it happens to be a view. I suppose you want to confirm user authentication (form.is_valid()
does not do that automatically).
More details are in the documentation of auth
module:
How to log a user in
If you have an authenticated user you want to attach to the current session - this is done with a
login()
function.login()
To log a user in, from a view, use
login()
. It takes an HttpRequest object and a User object.login()
saves the user’s ID in the session, using Django’s session framework.Note that any data set during the anonymous session is retained in the session after a user logs in.
This example shows how you might use both
authenticate()
andlogin()
:from django.contrib.auth import authenticate, login def my_view(request): username = request.POST['username'] password = request.POST['password'] user = authenticate(username=username, password=password) if user is not None: if user.is_active: login(request, user) # Redirect to a success page. else: # Return a 'disabled account' error message else: # Return an 'invalid login' error message.
As Paulo mentioned, AuthenticationForm
already handles password hashing. Please read the official documentation for examples:
Using the Django authentication system: Authentication in Web requests
Upvotes: 0
Reputation: 29794
I'm pretty sure you don't need to call make_password
in this one:
if 'password' in post:
post['password'] = make_password(post['password'])
form = AuthenticationForm(data=post)
Just pass the normal request.POST
to data
and the form itself do the encryption and test it against the database. This is the fragment of AuthenticationForm
's clean
method where it do this:
def clean(self):
username = self.cleaned_data.get('username')
password = self.cleaned_data.get('password')
if username and password:
self.user_cache = authenticate(username=username,
password=password)
...
You can see the whole definition here.
I suppose your using official make_password
function from django.contrib,auth
but take a look at the docs closely, normally, user register functions do this automatically so you won't have to do it.
Anyways:
Check the errors form is yielding after is_valid
call and change your login
code to this:
if request.method == 'POST':
form = AuthenticationForm(data=request.POST)
Hope this helps!
Upvotes: 2