Django csrf_protect decorator not working - django

I am using Django to build a web app. I am using Vue JS for the frontend. My problem is when ever I use csrf_protect its showing 403 error
My views:
#csrf_protect
def SignUpView(request):
if request.method == "POST":
form = SignUpForm(request.POST)
if form.is_valid():
form.save()
username, password = form.cleaned_data.get('username'), form.cleaned_data.get('password1')
new_user = authenticate(username = username, password = password)
login(request, new_user)
return redirect('/')
else:
form = SignUpForm()
return render(request, 'Accounts/SignUp.html', {'form':form})
#csrf_protect
def validateUsername(request):
username = request.GET.get('username', None)
usernameRegEx = r'^[a-zA-Z0-9#+-_.#]*$'
usernameRegExResult = {
'valid' : bool(re.search(usernameRegEx, username, re.M|re.I)),
'is_taken' : User.objects.filter(username=username).exists()
}
return JsonResponse(usernameRegExResult)
I read the Django docs which says I can use csrf_protect decorator above my view but in my case its not working. Somebody please help.

CSRF is a protection that prevents cross site request forgery. It works by generating an unique token that identify the form. So if you send data to your server without the token it gave you (through cookies for instance) it will not accept it.
If you have the CSRF middleware turned on you should not need CSRF protect decorator!

Related

how to call an url in django view function

I am trying to execute one of the url of urls.py with urllib in django view function. After execution i got error like
raise HTTPError(req.full_url, code, msg, hdrs, fp)
urllib.error.HTTPError: HTTP Error 411: Length Required
Is this possible to execute url with urllib inside django view function.
#login_required(login_url='http://domain/user/login?destination=apps/member/change_password')
def change_password(request):
'''Form for user to change their password'''
form = SetPasswordForm(user=request.user, data=request.POST or None)
if form.is_valid():
form.save()
ob = urllib.request.urlopen(url='http://domain/login/', data=request)
messages.success(request, 'Your password has been succesfully updated!')
return redirect('hq:profile')
return render(request, 'registration/password_change_form.html',
{'form': form})
when i execute urllib
Yes it is possible but keep in mind, that the time of that request will add up to your loading time.
If you do that from within the same django system you should think, if there would be a better solution.
In your case it may eventually use:
from django.contrib.auth import authenticate
authenticate(username, password)
I have solved my problem by modifying as below.
from django.contrib.auth import login
#login_required(login_url='http://domain/user/login?destination=apps/member/change_password')
def change_password(request):
'''Form for user to change their password'''
form = SetPasswordForm(user=request.user, data=request.POST or None)
if form.is_valid():
user = form.save()
user.is_active = True
user.save()
user.backend = "django.contrib.auth.backends.ModelBackend"
login(request, user)
messages.success(request, 'Your password has been succesfully updated!')
return redirect('hq:profile')
return render(request, 'registration/password_change_form.html',
{'form': form})

Django Cookie with Login function

I'm trying to set my first cookie with Django when users are logged on my application.
When user is logged, the template is well-displayed but none cookie in my application which is named : Cookie
My function looks like :
def Login(request):
error = False
if request.method == "POST":
form = ConnexionForm(request.POST)
if form.is_valid():
username = form.cleaned_data["username"]
password = form.cleaned_data["password"]
user = authenticate(username=username, password=password)
if user:
login(request, user)
toto = GEDCookie(request)
return render(request, 'Home_Homepage.html', {'toto':toto})
else:
error = True
else:
form = ConnexionForm()
return render(request, 'Authentication_Homepage.html', locals())
#csrf_exempt
def GEDCookie(request):
SID = Logger.login("test", "10test")
response = HttpResponse("Cookie")
response.set_cookie('Cookie', SID, max_age=None)
return response
I missed something in my script ?
This isn't how you use cookies at all.
Inside your Login view, you're calling a separate view - GEDCookie that returns an HTTP response. But instead of returning that response directly to the user, which would set the cookie, you're for some reason trying to insert it in a template. That doesn't make sense.
If you want to set a cookie in your login view, you need to do so on the response that you return to the user.
Note also that after a successful login (or other post), you should always redirect, not display a template directly. So:
if user:
login(request, user)
response = redirect('home')
response.set_cookie('whatever')
return response
Finally, you almost certainly don't need a cookie here in any case. If you want to store data related to the current user, use the session.
As you can clearly see that you are not attaching your cookie to your real response, you are passing it as the context in render function which is an issue.
def Login(request):
error = False
if request.method == "POST":
form = ConnexionForm(request.POST)
if form.is_valid():
username = form.cleaned_data["username"]
password = form.cleaned_data["password"]
user = authenticate(username=username, password=password)
if user:
login(request, user)
SID = Logger.login("test", "10test")
response = render(request, 'Home_Homepage.html', {})
response.set_cookie('Cookie', SID, max_age=None)
return response
else:
error = True
else:
form = ConnexionForm()
return render(request, 'Authentication_Homepage.html', locals())
https://docs.djangoproject.com/en/3.0/ref/request-response/#django.http.HttpResponse.set_cookie Please refer this link for individual arguments of inbuilt function.
Create signal.py in app. where your user model is present or add in main project directory and Add below snippet in signal.py
from django.db.models.signals import pre_save, pre_delete, post_save, post_delete
from django.dispatch import receiver
from django.dispatch import Signal
from allauth.account.signals import user_logged_in # it signal for post login
from django.shortcuts import render
#receiver(user_logged_in) # Decorator of receiving signal while user going to logged in
def post_login(sender, user, request, response, **kwargs):
response.set_cookie('team', 'india') # This will set cookie
return response
In given snippet, default response will come in argument, so direct redirect to that response, if you want to change then render other template using render/redirect django.shortcuts methods like below,
response = render(request, 'base.html', {})

How to resolve form resubmission?

When page refresh that post request, form resubmission happened.
I tried redirect after post request. but, it's not working when request have context. this context have form.errors because login.html show form error.
How to resolve this issue? (without Message Framework)
def do_login(request):
if request.method == 'POST':
form = LoginForm(request.POST)
if form.is_valid():
email = form.cleaned_data['email']
password = form.cleaned_data['password']
user = authenticate(email=email, password=password)
if user is not None:
login(request, user)
return redirect(reverse('root'))
else:
pass
# redirect cannot pass context, right?
else:
form = LoginForm()
context = {
'form': form
}
return render(request, 'accounts/login.html', context=context)
Your code is using the standard approach. You are redirecting after a successful post request, but not after an unsuccessful post. This allows the form to be displayed with errors.
If the user refreshes after an unsuccessful post, then the browser will usually warn the user that their data will be resubmitted. If they do resubmit, then it doesn't really matter, the login will fail again, and they will see the same errors as before.

Django auth backends and auto login

I'm trying to have a user login automatically as soon as they register. They have just input their desired username and two matching passwords and I would like to grant access to the site with no more friction. But my current view with an authenticate followed by a login using authenticate's user object doesn't work i.e. the view redirects to the profile page after register, but the profile page is #login_required decorator protected, and so redirects because the login was unsuccessful. I have widely debugged and looked around.
I've tried everything I can think of short of resorting to a third-party registration app. People have suggested there's a problem/peculiarity with the backends or something, but I just can't see why I can't register, auth and login in one view.
views.py (relevant parts)
#login_required
def user(request, user_id):
profile_user = User.objects.get(id=user_id)
context = RequestContext(request)
context['profile_user'] = profile_user
return render_to_response('profile.html', context)
def register(request):
if request.method == 'POST':
form = UserCreationForm(request.POST)
if form.is_valid():
new_user = form.save()
new_user = authenticate(username = request.POST['username'],
password = request.POST['password1'])
if new_user is not None:
login(request, new_user)
context = RequestContext(request)
context['user_id'] = new_user.id
context['new_user'] = new_user
url = '/user/%s/' % new_user.id
return HttpResponseRedirect(url)
else:
form = UserCreationForm()
return render_to_response("registration/register.html", {'form': form},
context_instance=RequestContext(request))
How do you deal with this?
You can make it work by:
Redirecting to an intermediate template through simple view, it will set the session cookie on client side, you can show a message like "Registration completed. logging in..."
Redirect to profile page after a small 3-5 seconds time out. This time, request will carry authentication cookie, profile page will be accessible.

Django forms always failing

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/