Home > Enterprise >  Is the implementation of my add to cart / remove from cart secure?
Is the implementation of my add to cart / remove from cart secure?

Time:10-13

I am building an ecom website and in order to implement an add_to_cart function I've done the following.

Clicking the add to cart button calls the javascript add_to_cart function that I wrote:

<button type="button" onclick = "add_to_cart({{ product.pk }})">Add to Cart</button>

This is the function:

function add_to_cart(product_pk) {
    let url = '/add-to-cart/'   product_pk.toString()
    $.ajax({
        type: 'GET',
        url: url,
        processData: false,
        contentType: false
    })
}

the urls for this look like this:

path('add-to-cart/<str:product_pk>', views.add_to_cart, name='add_to_cart')

and finally my view looks like this:

def add_to_cart(request, product_pk):

    cart = request.session['cart']
    cart.append(product_pk)
    request.session['cart'] = cart

    context = {'length_of_cart': len(cart)}

    return HttpResponse(content = dumps(context), content_type='application/json')

tldr: Click button, button calls js, js makes get request to url, url triggers view, logic in view adds product to cart.

I feel like this is pretty "hacky". Are there any security issues involved with what I've done here?

CodePudding user response:

I feel like this is pretty "hacky". Are there any security issues involved with what I've done here?

A GET request is not supposed to have side-effects. Indeed, as the HTTP specifications say [w3.org]:

In particular, the convention has been established that the GET and HEAD methods SHOULD NOT have the significance of taking an action other than retrieval. These methods ought to be considered “safe”.

You should make use of POST, PUT, PATCH or DELETE to make requests with side effects.

Django will automatically try to validate a CSRF token if you make a POST request. This to prevent a vulnerability that could result in a malicious JavaScript file that uses the credentials of the logged in user to make requests. Django (aims to) prevent this by using a CSRF token. You add such token to the POST request as is explained in the AJAX section of the documentation:

function getCookie(name) {
    let cookieValue = null;
    if (document.cookie && document.cookie !== '') {
        const cookies = document.cookie.split(';');
        for (let i = 0; i < cookies.length; i  ) {
            const cookie = cookies[i].trim();
            // 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;
}
const csrftoken = getCookie('csrftoken');

function add_to_cart(product_pk) {
    let url = '/add-to-cart/'   product_pk.toString()
    $.ajax({
        type: 'POST',
        url: url,
        processData: false,
        contentType: false,
        headers: {'X-CSRFToken': csrftoken}
    })
}

finally we should product the view to only accept POST requests with the @require_POST decorator [Django-doc]:

from django.views.decorators.http import require_POST

@require_POST
def add_to_cart(request, product_pk):
    # …
  • Related