Django Ajax CSRF error 403 or 500 - ajax

I try to change the admin interface. I have added a field to change the status of the Order in my shop application via Ajax.
I base on this Django snippet Admin list_display Ajax.
This is my JavaScript code:
$(document).ready(function() {
$('.order-helper').css("margin", "0");
$('.order-helper').blur(function(){
var input = $(this);
$.ajax({
url: "/ajax-status-update/"+ input.attr('name') +"/",
data: order=input.attr('value'),
type: "POST",
complete: function(xhr_obj, msg){
if (msg == 'success') {
input.css("border", "1px solid green");
} else {
input.css("border", "1px solid red");
}
},
});
});
});
This is my view:
def order_helper(request, prod_id):
prod = get_object_or_404(FixedOrder, id=prod_id)
prod.status = request.POST.get('order')
prod.save()
return HttpResponse(content='Ok', status=200)
The view works with not Ajax call.
I read tons of articles about this and nothing works for me. I know that it is connected somehow with CSRF. In the console I get a 403 error.
I read that I have to add this JavaScript snippet anywhere:
$(document).ajaxSend(function(event, 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;
}
function sameOrigin(url) {
// url could be relative or scheme relative or absolute
var host = document.location.host; // host + port
var protocol = document.location.protocol;
var sr_origin = '//' + host;
var origin = protocol + sr_origin;
// Allow absolute or scheme relative URLs to same origin
return (url == origin || url.slice(0, origin.length + 1) == origin + '/') ||
(url == sr_origin || url.slice(0, sr_origin.length + 1) == sr_origin + '/') ||
// or any other URL that isn't scheme relative or absolute i.e relative.
!(/^(\/\/|http:|https:).*/.test(url));
}
function safeMethod(method) {
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
if (!safeMethod(settings.type) && sameOrigin(settings.url)) {
xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
}
});
But if I add this I get 500 in the console. How can I check what kind of problem it is?
Maybe I miss a CSRF token?

Your data parameter to $.ajax is not escaped properly. The heart of your problem probably lies there:
$.ajax({
url: "/ajax-status-update/"+ input.attr('name') +"/",
data: "order=" + input.attr('value'),
type: "POST",
complete: function(xhr_obj, msg){
if (msg == 'success') {
input.css("border", "1px solid green");
} else {
input.css("border", "1px solid red");
}
},
});
If you want to continue to use the CSRF middleware, you should probably serialize a form instead:
data: $('#theForm').serialize(),

Related

Django: How to send csrf_token with Ajax

I have my Ajax in a jQuery function:
btnApplyConfig.js:
$(".btnApplyConfig").click(function(){
var token = $("input[name=csrfmiddlewaretoken]").val();
// Some other vars I'm sending properly
console.log('token: '+token); //printing correctly
$("#"+frm).submit(function(e){
e.preventDefault();
console.log('Post method via ajax');
$.ajax({
url: '/ajax/validate_config',
type: 'POST',
data: {
'token': token,
//and other stuff I'm sending properly
},
dataType: 'json',
});
});
});
my Django view:
def validate_config(request):
token = request.GET.get('token', None)
#some other vars I've sent ok with ajax
data = {
#some vars
'token': token,
}
if request.method == 'POST':
item = MyClass.objects.filter(my_keyword=my_filter_values).update(my_ajax_values)
return JsonResponse(data)
All the data is being processed properly, the only problem for me is that I'm getting the following error:
Forbidden (CSRF token missing or incorrect.): /ajax/validate_config/
I've put some prints in view in order to check if vars are being sent properly, and yes they are.
How could I handle it?
I checked some tutorials but I couldn't find a solution so far.
A very simpler way
let cookie = document.cookie
let csrfToken = cookie.substring(cookie.indexOf('=') + 1)
$.ajax({
url: 'url/path',
type: 'POST',
headers: {
'X-CSRFToken': csrfToken
}
})
You can use this. You don't have to put anything in your view for it. It will automatically find it.
$.ajax({
url: ,
type: "POST",
data: {
'csrfmiddlewaretoken': $("input[name=csrfmiddlewaretoken]").val()
// plus other data
},
dataType: 'json',
success: ,
});
You probably also want to add if request.is_ajax() to your view.
This was the solution that worked for me in this case:
Added this code before the Ajax code:
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) {
// 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) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});

Send file to Django througth Ajax

I was working with data just POSTing or GETting through AJAX until a file wanted to cause some problems :P
AJAX dosnt work if I have processData and contentType set to true. But if I set processData and contentType set to false, I got an CSRF TOKEN MISSING error.
How can I send the code with 'csrfmiddlewaretoken' and be able to manage the file too.
this is my jQuery code:
$(document).ready(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) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
function sameOrigin(url) {
// test that a given url is a same-origin URL
// url could be relative or scheme relative or absolute
var host = document.location.host; // host + port
var protocol = document.location.protocol;
var sr_origin = '//' + host;
var origin = protocol + sr_origin;
// Allow absolute or scheme relative URLs to same origin
return (url == origin || url.slice(0, origin.length + 1) == origin + '/') ||
(url == sr_origin || url.slice(0, sr_origin.length + 1) == sr_origin + '/') ||
// or any other URL that isn't scheme relative or absolute i.e relative.
!(/^(\/\/|http:|https:).*/.test(url));
}
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && sameOrigin(settings.url)) {
// Send the token to same-origin, relative URLs only.
// Send the token only if the method warrants CSRF protection
// Using the CSRFToken value acquired earlier
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});
$('.guardar-cambios-pedido').click(function(){
var url = $(this).data('url');
// Obtiene los datos de los inputs
if ($("#editarPedidoModal .checkAnuladoPedido").is(":checked")){
var anulado = true;
} else {
var anulado = false;
}
var codigo = $('.inputCodigoPedido').val();
var usuario = $('.inputUsuarioPedido').val();
var estado = $('.selectEstadoPedido').val();
var factura = $('.inputFacturaPedido').prop('files')[0];
// Crea un objeto datos
datos = {
'codigo': codigo,
'usuario': usuario,
'estado': estado,
'factura': factura,
'anulado': anulado,
}
// Envia los datos e los inputs al servidor
$.ajax({
type: 'POST',
url: url,
data: {'datos': datos},
processData: false,
//contentType: false,
//dataType: "multipart/form-data",
success: function(contenido){
//things done if success
}
});
. . . more code . . .
in my views.py
I'm trying to receive my data in this way:
if req.POST:
normal_data = req.POST.get('datos[key]', '')
file_data = req.FILES.get('datos[factura]', '')
UPDATE 1: I've updated my code and now the CSRF problem is gone.. What I have now is that i can't access data from the view.
AJAX call returns success, but no data even trying with datos['key'] or name of input.
Am I missing the way of "sending data"?
Finally, I found the solution by doing the following:
Added malsup jQuery form plugin: http://malsup.com/jquery/form/#getting-started
<script src="http://malsup.github.com/jquery.form.js"></script>
on my JS, I've setted the options and submited the form via ajaxSubmit()
$("#btn-submit").click(function(){
options = {
url: $('#form').prop('action'),
type: 'POST',
success: function(response) {
alert('Done');
}
};
$('#form').ajaxSubmit(options)
})
On my django views I get my data like any other POST request.
def some_view(request):
if request.POST:
other_inputs = request.POST.get('input_name', '')
file_input = request.FILES.get('input_name', '')
... more code ...
CSRF TOKEN on Header:
$(document).ready(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) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
function sameOrigin(url) {
// test that a given url is a same-origin URL
// url could be relative or scheme relative or absolute
var host = document.location.host; // host + port
var protocol = document.location.protocol;
var sr_origin = '//' + host;
var origin = protocol + sr_origin;
// Allow absolute or scheme relative URLs to same origin
return (url == origin || url.slice(0, origin.length + 1) == origin + '/') ||
(url == sr_origin || url.slice(0, sr_origin.length + 1) == sr_origin + '/') ||
// or any other URL that isn't scheme relative or absolute i.e relative.
!(/^(\/\/|http:|https:).*/.test(url));
}
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && sameOrigin(settings.url)) {
// Send the token to same-origin, relative URLs only.
// Send the token only if the method warrants CSRF protection
// Using the CSRFToken value acquired earlier
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});
}); // Ends document.ready
Cya!

HttpResponse. How to use it properly?

all. I am newest in Django and I have a question. I want learn what I need return to ajax get/post request. I have example, but I know it is not good. Can u please explain me about responses? When, what and why? I did not find any information about it.
When I click on button, object will delete from data base.
This is my ajax request:
function removeProduct(){
$('.btn-remove').click(function(e){
e.preventDefault();
var data = {};
data["csrfmiddlewaretoken"] = $('#quantity_goods [name="csrfmiddlewaretoken"]').val();
var product = $(this);
data.product_id = product.data("product_id");
var url = product.attr("action");
$.ajax({
url: url,
type: 'POST',
data: data,
cache: true,
success: location.reload(),
});
});
}
This is my view:
def remove_product(request):
"""Remove product from basket."""
data = request.POST
product_id = data.get('product_id')
product = ProductInOrder.objects.filter(id=product_id)
product.delete()
return HttpResponse()
Here's how I do it
var username_ok = false;
var email_ok = false;
/*CSRF Code */
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
function sameOrigin(url) {
// test that a given url is a same-origin URL
// url could be relative or scheme relative or absolute
var host = document.location.host; // host + port
var protocol = document.location.protocol;
var sr_origin = '//' + host;
var origin = protocol + sr_origin;
// Allow absolute or scheme relative URLs to same origin
return (url == origin || url.slice(0, origin.length + 1) == origin + '/') ||
(url == sr_origin || url.slice(0, sr_origin.length + 1) == sr_origin + '/') ||
// or any other URL that isn't scheme relative or absolute i.e relative.
!(/^(\/\/|http:|https:).*/.test(url));
}
/* End CSRF Code */
$(function() {
$('#username, #email').focus(function() {
var value = $(this).val();
if (value == 'required') {
$(this).val(null);
}
});
$('#username').change(function() {
var username = $(this).val();
var data = {'username': username};
var csrftoken = $.cookie('csrftoken');
$.ajax({
url: "/ajax_username",
type: "POST",
dataType: 'json',
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && sameOrigin(settings.url)) {
// Send the token to same-origin, relative URLs only.
// Send the token only if the method warrants CSRF protection
// Using the CSRFToken value acquired earlier
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
},
data: JSON.stringify(data),
success: function(response){
if (response['status'] == 'ok') {
if (response['exists'] == true) {
$('.username-exists').removeClass('hidden');
username_ok = false;
} else {
$('.username-exists').addClass('hidden');
username_ok = true;
}
}
}
});
/* End Ajax Call */
});
backend
import json
def username_ajax(request):
response = {'status': None}
if request.method == 'POST':
data = json.loads(request.body)
username = data['username']
response['exists'] = bool( User.objects.filter(username=username))
response['status'] = 'ok'
else:
response['error'] = 'no post data found'
return HttpResponse(
json.dumps(response),
content_type="application/json"
)
hope it helps

django/ajax: Unable to get Ajax post data in the views.py

I had a problem getting ajax post data from django backend, I don't know how to pass the value, please help.
In html I have simply this:
<form id="get_vulns_from_family">
<label for="family_content">Enter a family name to display the NVTs</label>
<input id="family_content" />
<input type="submit" value="search" />
</form>
In javascript I wrote this:
$(function() {
$("#get_vulns_from_family").submit(function(event) {
var family_text = $("#family_content").val();
var family_data = {"family": family_text};
$.ajax({
url: "/template_conf/get_vulns_from_family",
type: "POST",
data: family_data,
success: function(response) {
console.log(response);
},
error: function(response) {
console.log("failed!");
}
});
// prevent default posting of form
event.preventDefault();
});
});
In Django method corresponding to url /template_conf/get_vulns_from_family, I tried this:
def get_vuln_from_family(request):
family = request.POST['family']
# some other operations to get value for variable "json_data"
return HttpResponse(simplejson.dumps(json_data))
But django said: MultiValueDictKeyError: "Key 'family' not found in <QueryDict: {}>", which means the POST dictionary is empty.
Am I using the wrong way to get post data? If so what should I do? Thanks.
your url "/template_conf/get_vulns_from_family" is missing a trailing slash. django will typically redirect this to "/template_conf/get_vulns_from_family/", dropping the POST data
If your CSRF enabled then simple ajax post do not work. you will have to add the csrf token and set it to the ajax request header.
For Ajax POST request, you have to pass the CSRF token in as POST data with every POST request. For this reason, you must get CSRF token first. Since you have enabled CSRF protection so you will get the token from csrftoken cookie. The CSRF token cookie is named csrftoken by default. Acquiring the token is very straight forward and it can be achieved using the below code snippet.
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]);
if (cookie.substring(0, name.length + 1) == (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
function csrfSafeMethod(method) {
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
function sameOrigin(url) {
var host = document.location.host; // host + port
var protocol = document.location.protocol;
var sr_origin = '//' + host;
var origin = protocol + sr_origin;
return (url == origin || url.slice(0, origin.length + 1) == origin + '/') ||
(url == sr_origin || url.slice(0, sr_origin.length + 1) == sr_origin + '/') ||
!(/^(\/\/|http:|https:).*/.test(url));
}
$(function() {
$("#person_form_id").submit(function(event){
event.preventDefault();
$.ajax({
type:$(this).attr('method'),
url:"",
data:$(this).serialize(),
success: function(){
$('#message').html("<h2 style='color:green;'>Person Form Submitted!</h2>")
},
error: function(){
$('#message').html("<h2 style='color:red;'>Can't submit form</h2>")
}
});
return false;
});
});
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && sameOrigin(settings.url)) {
// Send the token to same-origin, relative URLs only.
// Send the token only if the method warrants CSRF protection
// Using the CSRFToken value acquired earlier
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});

Django CSRF failing with ajax

I have a problem with using Django CSRF with Ajax. I get a 403 Forbidden. I have done all the CSRF things that I normally do with a non-ajax request, but I still have this problem. I'm thinking this has something to do with the javascript snippet at https://docs.djangoproject.com/en/dev/ref/contrib/csrf/#ajax.
$(document).ajaxSend(function(event, 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;
}
function sameOrigin(url)
{
// url could be relative or scheme relative or absolute
var host = document.location.host; // host + port
var protocol = document.location.protocol;
var sr_origin = '//' + host;
var origin = protocol + sr_origin;
// Allow absolute or scheme relative URLs to same origin
return (url == origin || url.slice(0, origin.length + 1) == origin + '/') ||
(url == sr_origin || url.slice(0, sr_origin.length + 1) == sr_origin + '/') ||
// or any other URL that isn't scheme relative or absolute i.e relative.
!(/^(\/\/|http:|https:).*/.test(url));
}
function safeMethod(method)
{
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
if (!safeMethod(settings.type) && sameOrigin(settings.url))
{
xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
}
});
I'm not currently using this snippet, mostly because I don't understand a word of it and I don't know how to incorporate it into my jquery ajax call:
function submit_search()
{
$.ajax({
data: {query: document.search_form.query.value},
datatype: 'json',
success: function(data, textStatus, XMLHttpRequest)
{
if (data)
{
if (check_authentication(data))
{
$("#results").html("");
var results = data[0];
var length = data[1];
for (var index = 0; index < results.length; ++index)
{
var result = results[index];
$("#results").append("<p><a href='/entities/" + result["id"] + "'>" + result["name"] +
"</a><br />" + result["description"] + "</p>");
}
}
else
{
offer_login();
}
}
},
type: 'POST',
url: '/ajax/search',
});
}
Does anyone know how I should go about adding this snippet to my code?
Also tried:
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!(/^http:.*/.test(settings.url) || /^https:.*/.test(settings.url))) {
// Only send the token to relative URLs i.e. locally.
xhr.setRequestHeader("X-CSRFToken",
$("#csrfmiddlewaretoken").val());
}
}
});
but this also does not seem to work, although I'm not sure whether I should be doing something for the bit about #csrfmiddlewaretoken in my form
Thanks
All you need to do is paste the code block in such a way that the code in it runs. If you have a global JS file, you should be able to just add that JavaScript to the end of said file, and it will fix the problem.
well, couple steps required as stated in https://docs.djangoproject.com/en/dev/ref/contrib/csrf/
To summarize the tedious django doc, you will need to:
1. install jquery.cookie plugins
2. make sure crsf_token is passing around
for example, in your template, the form must contain the following hidden field
<input type="hidden" name="csrfmiddlewaretoken" value="{{csrf_token}}"/>
In your ajax request, you should so similar things like
csrf_token = $.cookie('csrftoken');
$.ajax({
url: '/url/',
type: 'POST',
beforeSend: function(xhr, settings) {
xhr.setRequestHeader("X-CSRFToken", csrf_token);
},
data: $('.form').serialize(), //assume you are submit a form
}).done(function(response){
console.log(response)
});
one small tricks that you might be missing is, your landing page(non-ajax) will need #csrf_protect decorator to set up cookie, if you don't do that, the cookie won't exists and the method will fail. If you don't want to do #csrf_protect decorator, you can always refer back to the doc and specifically setup the cookie. Either way will work.
Hope this helps.

Resources