0

I want to protect my functions from directly calling through browser url. May be it is possible through CSRF. But I am not able to do it. In front end side I am using ajax to call this function. So, the call should only be possible through ajax but not directly from browser url.

My javascript code is

function getData(table,id){
data = []
$.ajax({
    type: "POST",
    url: "getData",
    dataType:'json',
    data:{'tableName':table},
    success: function(result) {

        for(var i=0;i<result.length;i++){

            for (var key in result[i]){
                val = result[i][key]

                if (data.indexOf(val)==-1){
                    data.push(val)
                }
            }                   
        }
        $( "#"+id ).autocomplete({
          source: data
        });

    }
});

}

so I am calling this function in javascript.

In urls.py

from django.conf.urls import url
from . import views

urlpatterns = [
    url(r'^getData', views.getData, name='getData'),

]

In Views.py

def getData(request):
    tableName = request.POST.get('tableName')
    tableName = 'colleges'
    cursor = connection.cursor()
    query = "select * from "+tableName
    cursor.execute(query)

    columnDesc = cursor.description
    result=[dict(zip([col[0] for col in columnDesc], row))
        for row in cursor.fetchall()]

    return HttpResponse(json.dumps(result), content_type="application/json")

So, when i am calling through web browser url directly like...

http://localhost/shikshapp/getData

I am getting response from my views and i am able to see the data..

So, how can i protect this kind of call.. when the token is not there... But this call should be accessible through ajax

Tarun Khaneja
  • 451
  • 11
  • 23
  • try adding csrf token to the request like in this one https://stackoverflow.com/questions/5100539/django-csrf-check-failing-with-an-ajax-post-request and then validate csrf in view if match then procced `'request_csrf_token = request.META.get('HTTP_X_CSRFTOKEN', '')` and `if request_csrf_token != csrf_token: return self._reject(request, REASON_BAD_TOKEN) ` – Kalariya_M Nov 03 '17 at 04:50
  • i am getting error... global name csrf_token is not defined @Kalariya_M – Tarun Khaneja Nov 03 '17 at 07:01

1 Answers1

0

If you want to only accept POST request, you may add the require_http_methods decorator to your view as in:

@require_http_methods(["POST"])
def getData(request):
    tableName = request.POST.get('tableName')
    tableName = 'colleges'
    # ...

But if you want some security and prevent yourself from CSRF attacks, you need to add a CSRF token:

# On the main view (the one that contains JS), add this decorator
@ensure_csrf_cookie
def yourView(request):
    pass
    # ...

# On the ajax view, refuse all requests without any csrf_token
@require_http_methods(["POST"])
@csrf_protect
def getData(request):
    tableName = request.POST.get('tableName')
    tableName = 'colleges'
    # ...

Then your JS code must look like that:

// function to get token from cookie with 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;
}

// your function
function getData(table,id){
data = []
$.ajax({
    type: "POST",
    url: "getData",
    dataType:'json',
    data:{'tableName':table},
    beforeSend: function(xhr, settings) {
        // Add the CRSF header with the csrf cookie
        xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'););
    }
    success: function(result) {

        for(var i=0;i<result.length;i++){

            for (var key in result[i]){
                val = result[i][key]

                if (data.indexOf(val)==-1){
                    data.push(val)
                }
            }                   
        }
        $( "#"+id ).autocomplete({
          source: data
        });

    }
});
SebCorbin
  • 1,645
  • 1
  • 12
  • 23