Im a bit new to django and working on the user handling.
Now have i sorted it all and it works just fine, except for when a user enters faulthy data to login.
No errormessage is shown.
I was wondering if there would be a easier/better approach to fix this then putting a empty variable in all my views, except the invalid login. (to store the message in)
My auth_view:
def auth_view(request):
username = request.POST.get('username', '')
password = request.POST.get('password', '')
#returns None if not correct
user = auth.authenticate(username=username, password=password)
if user is not None:
auth.login(request, user)
return HttpResponseRedirect(reverse('index'))
else:
invalid_login = "ErrorMessage"
return HttpResponseRedirect(reverse('index')
index is just this at the moment:
def index(request):
return render(request, 'index.html')
How can i solve this? (or would you suggest i just approach it with the extra var everywhere)
With kind regards
Hans
Here is how i solved it:
def index(request):
"""Logs a user into the application."""
auth_form = AuthenticationForm(None, request.POST or None)
# The form itself handles authentication and checking to make sure passowrd and such are supplied.
if auth_form.is_valid():
login(request, auth_form.get_user())
return HttpResponseRedirect(reverse('index'))
return render(request, 'index.html', {'auth_form': auth_form}
Now problem is my style class from css doesnt seem to work anymore.
But well we are getting there
(used the UserAuthenticationForm here
Related
I'm having trouble when i try to update user password in django.
def password(request):
if request.method=="POST":
password =request.user.password
username=request.user.username
c_password=request.POST["current_password"]
new_password=request.POST["new_password"]
r_new_password=request.POST["retype_new_password"]
if password==c_password:
if new_password==r_new_password:
user =User.objects.get(username=username)
user.set_password(new_password)
user.save()
messages.info(request,"Successfully saved")
else:
messages.info(request,"PASSWORD DOES NOT MATCH")
else:
messages.info(request,"PASSWORD INCORRECT")
return render(request,"security.html")
When i fill the current password, it is giving me error password incorrect. But, when i fill pbkdf2_sha256$320000$Cb4s4nwqKwirdgo50ZdjLH$aeuSP3X+dSZXsv0XJB0XxkpwfsmU+PedMX9Jl50Zark=
, my password becomes correct and user password is updateable. My problem is I would like to fill in current password field as normal current password without getting the error.
You use authenticate(…) [Django-doc] to validate the password: this will retrieve the hashing algorithm and the salt, and check if the hashes match, so you can work with:
def password(request):
if request.method == 'POST':
c_password = request.POST['current_password']
new_password = request.POST['new_password']
r_new_password = request.POST['retype_new_password']
user = authenticate(username=request.user.username, password=c_password)
if user is not None:
if new_password == r_new_password:
user.set_password(new_password)
user.save()
messages.info(request, 'Successfully saved')
else:
messages.info(request, 'PASSWORDS DOE NOT MATCH')
else:
messages.info(request, 'PASSWORD INCORRECT')
return render(request, 'security.html')
There is however a PasswordChangeView [Django-doc] to change the password: this already implements the logic and uses a form. You can inject a different template, for example with:
path(
'password/change/',
PasswordChangeView.as_view(template_name='security.html'),
name='password_change'
)
Note: In case of a successful POST request, you should make a redirect
[Django-doc]
to implement the Post/Redirect/Get pattern [wiki].
This avoids that you make the same POST request when the user refreshes the
browser.
Note: You can limit views to a view to authenticated users with the
#login_required decorator [Django-doc].
Note: It is better to use a Form [Django-doc]
than to perform manual validation and cleaning of the data. A Form will not
only simplify rendering a form in HTML, but it also makes it more convenient
to validate the input, and clean the data to a more convenient type.
Refer the Documentation Django does not store raw (plain text) passwords on the user model
use authenticate function instead of using if password==c_password:.
from django.contrib.auth import authenticate
def password(request):
if request.method=="POST":
password =request.user.password
username=request.user.username
c_password=request.POST["current_password"]
new_password=request.POST["new_password"]
r_new_password=request.POST["retype_new_password"]
user = authenticate(username=username, password=c_password)
if user is not None:
if new_password==r_new_password:
user =User.objects.get(username=username)
user.set_password(new_password)
user.save()
messages.info(request,"Successfully saved")
else:
messages.info(request,"PASSWORD DOES NOT MATCH")
else:
messages.info(request,"PASSWORD INCORRECT")
return render(request,"security.html")
I am trying as hard as I can to learn to concept of authentication within the Django framework. I am reading the documentation and trying to code similar which will help me get the subject. At the moment I am trying to implement a simple login which redirects to a page. If the user is logged in he should see a message other wise he should see a different message. This is my code.
I have made a simple login form
class LoginForm(forms.Form):
username = forms.CharField()
password = forms.CharField(widget=forms.PasswordInput())
this is my login view
def login_view(request):
if request.method == 'POST':
form = LoginForm(request.POST)
if form.is_valid():
username = form.cleaned_data['username']
password = form.cleaned_data['password']
user = authenticate(request, username=username, password=password)
if user is not None:
login(request, user)
return redirect('/users/success/')
else:
return redirect('/users/success/')
else:
form = LoginForm()
return render(request, 'testauth/login.html', {'form': form})
(I know the above code is a little bit redundant ... at the moment this is not so important)
and this is the success view
def success_view(request):
print(request.user)
if request.user.is_authenticated:
return HttpResponse("logged in")
else:
return HttpResponse("you are not logged in")
The problem is, I always get the "logged in" message even with users which do not exist. I tried restarting the server my cache is disabled ... I have no idea why is this happening. Why is this happening?
(p.s. I do not want to set in the settings.py a login success url. I want to do everything manually because I am struggling a lot with this topic and I want to make sure that I truly understand everything)
BACKGROUND:
I'm using the versatile django-brake for rate limiting in my Django app. I now need to configure it to limit brute force login attempts in my app too.
The way to do that is to decorate the login view with the decorator ratelimit(field='username') and adding was_limited = getattr(request, 'limited', False) inside the view. was_limited is True if the same username (OR IP) is used >5 times/min. One can then redirect offending users, etc.
SCENARIO:
Currently, I'm using the login function in django.contrib.auth.views. I can decorate this function in my urls.py. But I can't include was_limited = getattr(request, 'limited', False) inside the function that way. And that is mission critical, since only once that flag is True can I take action against the offending user.
QUESTION:
So what's the best way for me to decorate and extend this function to include the above functionality? Do I need to override the whole thing, and if so, how? Please advise. I can directly write the required code in django.contrib.auth.views, but that's a hack.
Being a beginner, I'm trying to come up with the best way to deal with a situation like this. An illustrative example would be nice.
For reference, I'm including django.contrib.auth.views.login below:
#sensitive_post_parameters()
#csrf_protect
#never_cache
def login(request, template_name='registration/login.html',
redirect_field_name=REDIRECT_FIELD_NAME,
authentication_form=AuthenticationForm,
current_app=None, extra_context=None):
"""
Displays the login form and handles the login action.
"""
redirect_to = request.REQUEST.get(redirect_field_name, '')
if request.method == "POST":
form = authentication_form(data=request.POST)
if form.is_valid():
# Ensure the user-originating redirection url is safe.
if not is_safe_url(url=redirect_to, host=request.get_host()):
redirect_to = resolve_url(settings.LOGIN_REDIRECT_URL)
# Okay, security check complete. Log the user in.
auth_login(request, form.get_user())
if request.session.test_cookie_worked():
request.session.delete_test_cookie()
return HttpResponseRedirect(redirect_to)
else:
form = authentication_form(request)
request.session.set_test_cookie()
current_site = get_current_site(request)
context = {
'form': form,
redirect_field_name: redirect_to,
'site': current_site,
'site_name': current_site.name,
}
if extra_context is not None:
context.update(extra_context)
return TemplateResponse(request, template_name, context,
current_app=current_app)
All the work is already done in the decorator, by the looks of things. The examples show adding was_limited if you want to do something extra inside the view to say that requests were previously limited, but there's certainly no need to do so and it won't have any effect on the functionality.
I tried this and its working. See the reference from https://docs.djangoproject.com/en/1.10/topics/auth/default/
def my_login(request,*args,**kwargs):
if request.method == 'POST':
username = request.POST['username']
password = request.POST['password']
if username and password:
user = authenticate(username=username, password=password)
if user:
login(request, user)
return redirect('/home')
else:
return render(request, 'login.html')
else:
return render(request, 'login.html')
return render(request, 'login.html')
I am working on a sign in page in Django, but I am using Userena. I have attached the view method for the signin in Userena below. The problem is that since all the views I have written previously to this were MUCH shorter and concise. I'm having trouble trying to figure out where in this method I would add something in to "do something if password is wrong". Ideally, what I would like to do is if the password is wrong, trigger a popup in javascript. I'm guessing I first have to add something to this view method that indicates the password is wrong though?
#secure_required
def signin(request, auth_form=AuthenticationForm,
template_name='userena/signin_form.html',
redirect_field_name=REDIRECT_FIELD_NAME,
redirect_signin_function=signin_redirect, extra_context=None):
form = auth_form()
if request.method == 'POST':
form = auth_form(request.POST, request.FILES)
if form.is_valid():
identification, password, remember_me = (form.cleaned_data['identification'],
form.cleaned_data['password'],
form.cleaned_data['remember_me'])
user = authenticate(identification=identification,
password=password)
if user.is_active:
login(request, user)
if remember_me:
request.session.set_expiry(userena_settings.USERENA_REMEMBER_ME_DAYS[1] * 86400)
else: request.session.set_expiry(0)
if userena_settings.USERENA_USE_MESSAGES:
messages.success(request, _('You have been signed in.'),
fail_silently=True)
#send a signal that a user has signed in
userena_signals.account_signin.send(sender=None, user=user)
# Whereto now?
redirect_to = redirect_signin_function(
request.REQUEST.get(redirect_field_name), user)
return HttpResponseRedirect(redirect_to)
else:
return redirect(reverse('userena_disabled',
kwargs={'username': user.username}))
if not extra_context: extra_context = dict()
extra_context.update({
'form': form,
'next': request.REQUEST.get(redirect_field_name),
})
return ExtraContextTemplateView.as_view(template_name=template_name,
extra_context=extra_context)(request)
check user present or not like :
if user:
if user.is_active:
login(request,user)
else:
# account disabled
else:
#invalid login detailed
return response
I'm trying to use Django's built in authentication modules. For the site I'm working on I want to use email addresses as login names and not just the normal alphanumeric fields they're usually set to. In order to do this I changed all the String fields to Email fields and changed their max length from 30 to 320. My registration code appears to be working fine but not my login code. Here is what I'm using right now:
def login(request):
if request.method == 'POST':
form = AuthenticationForm(request.POST)
if form.is_valid():
return HttpResponse("valid")
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)
return HttpResponseRedirect("/")
# Redirect to a success page.
else:
return HttpResponse("Disabled Account")
# Return a 'disabled account' error message
else:
return HttpResponse("Invalid Login")
# Return an 'invalid login' error message.
else:
return HttpResponse("%s" % repr(form.errors))
else:
form = AuthenticationForm()
return render_to_response("login.html", {'form': form, }, context_instance=RequestContext(request))
No matter what I submit, form.is_valid() is returning FALSE but form.errors is empty. Any ideas what might be wrong? I think I changed everything over to Email properties so I don't think that's it. Also, in case it changes anything I'm trying to do this on google app engine using djangoappengine.
Sorry, but you cannot use Django's authentication module on top of google app engine. Django uses its own special database backend which is similar to google-app-engine's but is not drop-in compatible.
If you want to do authentication on GAE, you should do it the google-app-engine way:
http://code.google.com/appengine/docs/python/users/