Mako csrf_token like in Django templates - django

I my recent Django-project I use mako templates.
About Cross Site Request Forgery CSRF.
In django templates there is the tag {% csrf_token %} to protect from hackers.
What about mako templates? Is there any analog of csrf_token or there is another protection mechanism???
Thanks!

I ran into the same problem just today (that's why I ended up here). I found a solution, at least, for what I wanted to do, which is pass some POST data to another view through an HTML form. Here it is:
From your first view, get a CSRF Token and add it to your (Mako) context:
from djangomako.shortcuts import render_to_response as render
from django.core.context_processors import csrf
def first_view(request):
"""This view generates a form whose action is 'second_view'."""
context = { "csrftoken": csrf(request)["csrf_token"] }
return render("path/to/yourtemplate.html", context)
yourtemplate.html's form must have a field named “csrfmiddlewaretoken” whose value is the CSRF Token, which we placed in the context as “csrftoken”. As in:
<input type="hidden" name="csrfmiddlewaretoken" value="${ csrftoken }" />
Source: Cross Site Request Forgery protection (Django 1.5 Docs)

There's some sample code at Django Snippets that looks to do this, although judging by the comments, you may need to fiddle a bit. If you have trouble, you basically want to make sure that you're duplicating the Django stock CSRF tag (click the link, start on line 87).

Related

Django: CSRF is incorrect or missing

I have seen a number of forums and posts but still couldn't get the handle of it. Here in django doc, it says
The CSRF middleware is activated by default in the MIDDLEWARE setting. If you override that setting, remember that 'django.middleware.csrf.CsrfViewMiddleware' should come before any view > middleware that assume that CSRF attacks have been dealt with.
If you disabled it, which is not recommended, you can use csrf_protect() on particular views you want to protect (see below).
In any template that uses a POST form, use the csrf_token tag inside the > element if the form is for an internal URL, e.g.:
form action
{% csrf_token %}
Based on that, in my html template I did simply:
<form id='frm' name='frm' method="post" action="{% url 'gettip' %}" >
{% csrf_token %}
<input type="text" name="tipid" name="tipid">
<input type="submit" value="Get Tip Value"/>
</form>
I expected the CSRF_token to create the hidden element since the middleware is already loaded. I see no element in the form and I get CSRF error.
The form is not associated with any model. I haven't used forms.py either. My current view is simply to output something:
def gettip(request):
if request.POST:
return HttpResponse('You requested a tip')
#from a weblink, i was told to add the following but it made no difference
context = {}
return render_to_response('tip.html',context, context_instance=RequestContext(request))
The error I am getting is obviously CSRF missing cos the hidden element is not there at all.
I am migrating from PHP and this is giving me a hard time. Though my form is not for login purposes, I couldn't get this one to work either for the same error. I am on django 1.10 and just want to get a positive response when form is submitted.
Don't use render_to_response, it's obsolete. Use render instead.
from django.shortcuts import render
def gettip(request):
if request.POST:
return HttpResponse('You requested a tip')
context = {}
return render(request, 'tip.html', context)
If the template containing the form is rendered by another view, you'll have to fix that view as well.

Restricting Access to Django's success_url()

New Django user here.
I am trying to restrict access to Django's success_url() upon GET requests. I realize I am not the first to ask this question, however, I am specifically trying to achieve this in conjunction with Django's generic class-based views. Generic views seem cleaner, faster, and more idiomatic. I want to use them as much as possible unless they are absolutely unfit for the job.
Basically, I am creating a simple contact form for non-users who only want to send me a message without creating an account. I've created a contact app to handle these types of contacts. I've created a ModelForm, which I am rendering with a contact.html with Django's FormView. After a person submits the form, they will receive a cool looking thank you message, rendered with a thanks.html, which has its own url.
But I only want them to see the thank you message if they POST the contact form. Currently, you can go on my site and type '/contact/thanks/', and my thanks.html will be rendered whether you've submitted a form or not. Django's success_url apparently defaults to a GET request.
Here's my view:
class MyContact(FormView):
template_name = 'contact.html'
form_class = ContactForm
success_url = 'thanks'
Here's my form:
ContactForm(forms.ModelForm):
class Meta:
model = Contact
fields = ['email_address', 'message_body']
Here's the html form in contact.html:
<form action="" method="POST">{% csrf_token %}
{{ form|crispy }}
<button type="submit" class="send btn btn-secondary">Send Message</button>
</form>
My first thought was to decorate my contact app url with a require_POST() decorator like this:
urlpatterns = [
url(r'^thanks/$', require_POST(views.ThanksPageView.as_view()), name='thanks'),
]
This doesn't work because Django's success_url() defaults to a GET request.
What is the most idiomatic way to approach this? Since Django is a 'batteries included' framework, I do not want to use 'duck-tape', meaning I do not want implement any ad-hoc logic in my views or urls.
Sorry if I've missed anything in the docs or questions archive.
Since you're asking for a idiomatic approach, I would consider the messages framework and specifically the SuccessMessageMixin. This would allow you to add a success message to e.g. the contact form itself and the url-pattern for the /thanks/ page would not be necessary.

Can't Get CSRF Token to Appear on a Django Template/View

I'm trying to use a Django ListView sub-class to generate a page with a form on it. It's an old school manual HTML form, not a Django-generated one (though I do also have a Django-generated form elsewhere on the same page). Since Django bakes CSRF authentication in, I need to include the CSRF token in that form in order to make it work.
However, I'm not having much luck, even after looking at several related Stack Overflow posts (and fixing things accordingly).
Basically I've got a get method on a ListView subclass, and I've used the method decorator to decorate it with the CSRF decorator:
class FooView(ListView):
#method_decorator(ensure_csrf_cookie)
def get(self, request):
# code for otherwise working view
In my template I have:
<form>
{% csrf_token %}
However, when I view the source of the page after it's been rendered, I just see:
<form>
(no CSRF token).
I'm not explicitly adding the CSRF token to the context because I'm using ListView, and as per https://docs.djangoproject.com/en/1.6/ref/contrib/csrf:
If you are using generic views or contrib apps, you are covered already
I'm sure I'm just missing something basic, but any help explaining what that might be would be greatly appreciated.
You need import this:
from django.template import RequestContext
and then use it like so:
def example():
# Some code
return render_to_response('my_example.html', {
'Example_var':my_var
}, context_instance=RequestContext(request))
This will force a {% csrf_token %} to appear.

Forms with and without csrf tokens on single page

I have a login form on every page that's a popup, and it requires the csrf token.
I also have some form views that have a form that doesn't require the csrf token.
What I've found is that even if I have the {% csrf_token %} on the login form, if the view isn't wrapped with csrf_protect() it doesn't generate the token, so when the login form is submitted, it gets a csrf missing error. OTOH, if I do wrap it, then the other form on the page that doesn't need it complains about it missing though the login form works. One form submits to the current page form view, while the form submits to a separate form view.
Is it possible to get the csrf_token to generate even without the csrf_protect being used?
I saw the csrf_exempt function but it doesn't help when wrapping the view either. Is it possible to render two view functions or wrap it within the template? I'm just using a {% include login.html %}
Thanks

Django 1.2 CSRF and HTTP posts from Google Web Toolkit

I have a GWT web app working with Django server-side. I recently upgraded Django to 1.2, and am not able to get HTTP posts to work from my GWT app. I am getting this error:
CSRF verification failed. Request
aborted.
Reason given for failure:
CSRF token missing or incorrect.
I have enabled the csrf middlewares ('django.middleware.csrf.CsrfViewMiddleware', 'django.middleware.csrf.CsrfResponseMiddleware') which is working for contrib apps like login, but it seems as though the token is not getting added to posts made through GWT. Any ideas? Thanks in advance.
If you have checked the templates for auth.login you'll notice that a CSRF token is explicitly included inside the <form> tag.
<form method="post" action=".">
{% csrf_token %}
This is expanded into a hidden field when the page is rendered on a GET request. Something like:
<form method="post" action=".">
<div style='display:none'>
<input type='hidden' name='csrfmiddlewaretoken'
value='90064bf0e86edacfdb60595e3e2b8f23' />
</div>
This token is then passed back to the view on POST and validated.
Consequently before you can POST to a CSRF protected view you will have to first get the token from the said view.
Can you verify/ensure that you have the CSRF token handy before making a POST request to the view? Alternately you can disable CSRF protection for the view using the csrf_exempt decorator. This may not be a good idea though.
Update
This is the point of my question: I am not using django templates for my front-end and thus I cannot tag forms with the token. I am using GWT for my front-end, which is rendering the form for the post.
Are you already making a GET request to the Django view before rendering the page? In that case you can get the CSRF token by parsing the contents of the response.
If not you will have to explicitly make a GET request to the view (assuming it supports GET) and parse the response for a CSRF token. For an example see this question.