django csrf token with js - javascript

i'm trying to add to the html page a form with js (like the html token {% csrf_token %} when loading the page does):
table += "<td><form action='' method='post'>";
table += "<input type='submit' value='Delete?' />";
table += "</form></td>;
$("#tbody").append(table);
my problem is that i get a csrf validation error:
Forbidden (403)
CSRF verification failed. Request aborted.
Help
Reason given for failure:
CSRF token missing or incorrect.
i tried to add a custom csrf token:
var buf = new Uint8Array(1);
window.crypto.getRandomValues(buf);
table += "<input type='hidden' name='csrfmiddlewaretoken' value='" + buf[0] + "'>";
but i still get an error.
i also have in my js file the following code (which i got from the django website - and i don't know how it actually works..):
//enable csrf post ajax
//This function gets cookie with a given name
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie != '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) == (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
var csrftoken = getCookie('csrftoken');
/*
The functions below will create a header with csrftoken
*/
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain &&
(!(/^http:.*/.test(settings.url) || /^https:.*/.test(settings.url)))) {
// Only send the token to relative URLs i.e. locally.
xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
}
}
});
is there a way to add a csrf token with js the way i tried or it can not be?

The Javascript code provided by django for csrftoken extraction assigns csrftoken value to a variable named csrftoken
You can access it anywhere by its variable name, like this:
table += "<input type='hidden' name='csrfmiddlewaretoken' value='" + csrftoken + "'>";
Make sure you've included the js provided by django in your page before accessing csrftoken
Also, as #Sander pointed out, if you're using inline JS you can directly use csrf_token template tag instead.
table += "{% csrf_token %}";

Is the js added as inline js to your django template?
In that case you can do:
table += "<td><form action='' method='post'>";
table += "{% csrf_token %}";
table += "<input type='submit' value='Delete?' />";
table += "</form></td>;
$("#tbody").append(table);

Related

redirect to another page with post instead of get data [duplicate]

This question already has answers here:
JavaScript post request like a form submit
(32 answers)
Closed 7 years ago.
Basically what I want to do is send POST data when I change the window.location, as if a user has submitted a form and it went to a new page. I need to do it this way because I need to pass along a hidden URL, and I can’t simply place it in the URL as a GET for cosmetic reasons.
This is what I have at the moment, but it doesn’t send any POST data.
if(user has not voted) {
window.location = 'http://example.com/vote/' + Username;
}
I know that you can send POST data with jQuery.post(), but I need it to be sent with the new window.location.
So to recap, I need to send api_url value via POST to http://example.com/vote/, while sending the user to the same page at the same time.
For future reference, I ended up doing the following:
if(user has not voted) {
$('#inset_form').html('<form action="http://example.com/vote/' + Username + '" name="vote" method="post" style="display:none;"><input type="text" name="api_url" value="' + Return_URL + '" /></form>');
document.forms['vote'].submit();
}
per #Kevin-Reid's answer, here's an alternative to the "I ended up doing the following" example that avoids needing to name and then lookup the form object again by constructing the form specifically (using jQuery)..
var url = 'http://example.com/vote/' + Username;
var form = $('<form action="' + url + '" method="post">' +
'<input type="text" name="api_url" value="' + Return_URL + '" />' +
'</form>');
$('body').append(form);
form.submit();
Construct and fill out a hidden method=POST action="http://example.com/vote" form and submit it, rather than using window.location at all.
Here's a simple small function that can be applied anywhere as long as you're using jQuery.
var redirect = 'http://www.website.com/page?id=23231';
$.redirectPost(redirect, {x: 'example', y: 'abc'});
// jquery extend function
$.extend(
{
redirectPost: function(location, args)
{
var form = '';
$.each( args, function( key, value ) {
value = value.split('"').join('\"')
form += '<input type="hidden" name="'+key+'" value="'+value+'">';
});
$('<form action="' + location + '" method="POST">' + form + '</form>').appendTo($(document.body)).submit();
}
});
Here is a method, which does not use jQuery.
I used it to create a bookmarklet, which checks the current page on w3-html-validator.
var f = document.createElement('form');
f.action='http://validator.w3.org/check';
f.method='POST';
f.target='_blank';
var i=document.createElement('input');
i.type='hidden';
i.name='fragment';
i.value='<!DOCTYPE html>'+document.documentElement.outerHTML;
f.appendChild(i);
document.body.appendChild(f);
f.submit();
If you are using jQuery, there is a redirect plugin that works with the POST or GET method. It creates a form with hidden inputs and submits it for you. An example of how to get it working:
$.redirect('demo.php', {'arg1': 'value1', 'arg2': 'value2'});
Note: You can pass the method types GET or POST as an optional third parameter; POST is the default.
The answers here can be confusing so i will give you a sample code that i am working with.
To start with note that there is no POST parameter to java script windows.location function that you are referring to.
So you have to...
Dynamically make a form with a POST parameter.
Dynamically put a textbox or textboxes with your desired values to post
Invoke the submit form you dynamically created.
And for the example.
//---------- make sure to link to your jQuery library ----//
<script type="text/javascript" >
var form = $(document.createElement('form'));
$(form).attr("action", "test2.php");
$(form).attr("method", "POST");
$(form).css("display", "none");
var input_employee_name = $("<input>")
.attr("type", "text")
.attr("name", "employee_name")
.val("Peter" );
$(form).append($(input_employee_name));
var input_salary = $("<input>")
.attr("type", "text")
.attr("name", "salary")
.val("1000" );
$(form).append($(input_salary));
form.appendTo( document.body );
$(form).submit();
</script>
If all is done well, you shall be redirected to test2.php and you can use POST to read passed values of employee_name and salary; that will be Peter and 1000 respectively.
On test2.php you can get your values thus.
$employee_name = $_POST['employee_name'];
$salary = $_POST['salary'];
Needless to say , make sure you sanitize your passed values.
Generic function to post any JavaScript object to the given URL.
function postAndRedirect(url, postData)
{
var postFormStr = "<form method='POST' action='" + url + "'>\n";
for (var key in postData)
{
if (postData.hasOwnProperty(key))
{
postFormStr += "<input type='hidden' name='" + key + "' value='" + postData[key] + "'></input>";
}
}
postFormStr += "</form>";
var formElement = $(postFormStr);
$('body').append(formElement);
$(formElement).submit();
}
This is quite handy to use:
var myRedirect = function(redirectUrl, arg, value) {
var form = $('<form action="' + redirectUrl + '" method="post">' +
'<input type="hidden" name="'+ arg +'" value="' + value + '"></input>' + '</form>');
$('body').append(form);
$(form).submit();
};
then use it like:
myRedirect("/yourRedirectingUrl", "arg", "argValue");
var myRedirect = function(redirectUrl) {
var form = $('<form action="' + redirectUrl + '" method="post">' +
'<input type="hidden" name="parameter1" value="sample" />' +
'<input type="hidden" name="parameter2" value="Sample data 2" />' +
'</form>');
$('body').append(form);
$(form).submit();
};
Found code at http://www.prowebguru.com/2013/10/send-post-data-while-redirecting-with-jquery/
Going to try this and other suggestions for my work.
Is there any other way to do the same ?
You can use target attribute to send form with redirect from iframe.
Your form open tag would be something like this:
method="post" action="http://some.url.com/form_action" target="_top"
SOLUTION NO. 1
//your variable
var data = "brightcherry";
//passing the variable into the window.location URL
window.location.replace("/newpage/page.php?id='"+product_id+"'");
SOLUTION NO. 2
//your variable
var data = "brightcherry";
//passing the variable into the window.location URL
window.location.replace("/newpage/page.php?id=" + product_id);
details

javascript post django form gives csrf error

I have a html form like:
<form id="comment" action="{% url "url_name" ur.id %}" method="post">{% csrf_token %}
<textarea required="required" maxlength="255" rows="4" class="form-control" name="comment">
</textarea>
<button class="btn btn-default" onclick="add_comment(event)">Comment</button>
</form>
It is a html form and not django's form.
Here I have included csrf token in the form. I have post this form form javascript and now it gives me csrf verification failed error.
What am I missing here ? Is it mandatory to create form from django' form class to use csrf token ?
Need help
My js looks like:
function add_comment(event) {
event.preventDefault()
var form = document.getElementById('comment')
var url = form.action
var method = form.method
var form_data = new FormData(form)
fetch(url, {method: method, body: form_data})
}
and I am just rendering a template from my django view
When I see request network, csrf token and comment are passed as request payload ..
This GitHub issue suggests that you have to include the credentials, so that the CSRF cookie is sent with the request.
fetch(url, {method: method, body: form_data, credentials: 'include'})
I assume you're using AJAX to post the form. When posting forms with Django using AJAX you need to add the following to your Javascript before submitting the AJAX request:
$.ajaxSetup({
beforeSend: function(xhr, settings) {
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie != '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) == (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
if (!(/^http:.*/.test(settings.url) || /^https:.*/.test(settings.url))) {
// Only send the token to relative URLs i.e. locally.
xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
}
}
});
More info can be found at https://docs.djangoproject.com/en/1.10/ref/csrf/#ajax

how to apply csrf_token in django

In Django Template Without using form i want to upload files to my web server. so for that i`m using javascript library called dropzonejs.
I exactly follow this tutorial bootstrap dropzonejs. I setup everything to run the demo.
You see i decided not to use form so obviously the problem csrf_token is missing when upload happens time.
My doubt is how to include csrf_token in javascript. ?
This is the information they added in their home page for how to add csrf token
sending - Called just before each file is sent. Gets the xhr object and the formData objects as second and third parameters, so you can modify them (for example to add a CSRF token) or add additional data.
Are you understand my question ? give me some idea to do that ?
You could either have the view CSRF exempt:
from django.views.decorators.csrf import csrf_exempt
class YourView(models.View):
#csrf_exempt
def dispatch(self, *args, **kwargs):
return super(YourView, self).dispatch(*args, **kwargs)
The JavaScript config would probably look something similar to this:
(function($){
$(function(){
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie != '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) == (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
var csrftoken = getCookie('csrftoken');
function csrfSafeMethod(method) {
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
crossDomain: false,
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type)) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});
});
})(jQuery);

Csrf token not bein accepted by form rendered in javascript

I'm trying to render a form through javascript in django. I tried inserting the csrf token tag through the ways described in stack overflow post How do I include Django 1.2's CSRF token in a Javascript-generated HTML form? but it did not work for me :/ I've been trying for hours to find out the reason!
var CSRF_TOKEN = document.getElementById('csrf_token').value;
for (i = 0; i < this.ShoeList.length; i++) {
html += "<form method='POST' action='/AddToCart/'>'"+CSRF_TOKEN+"'<div class = 'box'<li><img src=' " + this.ShoeList[i].imageSource + "'/>";
}
and this is my template code:
<body onload="start()">
<input id="csrf_token" value="{{ csrf_token }}"/>
</body>
The token value is being displayed correctly when i run the code. But it does not accept the token for some reason. Please help!
for (i = 0; i < this.ShoeList.length; i++) {
html += "<form method='POST' action='/AddToCart/'>{% csrf_token %}<div class = 'box'<li><img src=' " + this.ShoeList[i].imageSource + "'/>";
}
var CSRF_TOKEN = document.getElementById('csrf_token').value;
for (i = 0; i < this.ShoeList.length; i++) {
html += "<form method='POST' action='/AddToCart/'><input type='hidden' value='"+CSRF_TOKEN+"' name='csrfmiddlewaretoken'><div class = 'box'<li><img src=' " + this.ShoeList[i].imageSource + "'/>";
}

Edit form field in Django on click and update in database

Here's what I am looking for.
I have an UpdateView, which renders the form from CreateView with fields loaded from database. Instead my edit form has readonly html attribue. So what I need is to drop readonly on click on the form field and when i enter new value it will be automaticaly updated when cursos moves to the next field.
How do i handle POST actions with out submit button?
you can use JavaScript(Jquery) to do so, blur event
EDITED: about CSRF verification,see https://docs.djangoproject.com/en/dev/ref/contrib/csrf/#ajax
about $.post see:https://api.jquery.com/jQuery.post/
template.html
<script type="text/javascript" src="/media/js/jquery-1.10.2.min.js"></script>
<script>
// using jQuery
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie != '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) == (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
$(document).ready(function(){
$("#myinput").blur(function(){
var csrftoken = getCookie('csrftoken');
$.ajaxSetup({
beforeSend: function(xhr) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
});
$.post('/link-to-fun/',{"value":value});
});
});
</script>
<input type="text" id="myinput">
url.py
write a special url(/link-to-fun/) to function in views.py
url(r'^link-to-fun$', views.change_db_value),
views.py
def change_db_value(request):
value = request.POST.get('value','')
# database operation

Categories