简体   繁体   中英

Django - Ajax request on mobile giving 403 forbidden even when CSRF token is set

I am having trouble testing a website that I am developing with django on mobile platforms. I have my server set up so that it uses javascript to continuously load posts using ajax from a django view while scrolling.

When I run my server from the command line and test it out on a desktop browser, the service runs fine and my posts load continuously without any 403 forbidden errors. However, when I try to test it on my mobile phone I can see in the command output of my server that a request has been given a 403 forbidden response.

I am unsure of anything that could be causing this, as I have taken into account the need for a csrf token to be loaded before ajax calls are made.

Here is the code that I use to load my csrf token.

$(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]);
              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({
      beforeSend: function(xhr, settings) {
          if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
              xhr.setRequestHeader("X-CSRFToken", csrftoken);
          }
      }
  });

});

Here is the code for the view that is called continuously through ajax.

# Get a post item
def get_posts (request):
    # Catch any errors
    try:
        # Request for home post
        if request.POST['type'] == 'home':
            # Post index to fetch
            index = int(request.POST['index'])
            # Fetch the post of the specified index
            posts = HomePost.objects.all()
            # Specified index does not exist
            if index >= len(posts):
                # 400 client error response
                return HttpResponse(status='400')
            # Template the post into an html string, cut off './' from image url
            post_html = render_to_string('home_post.html', {'image': str(posts[index].image)[2:], 'body': posts[index].body});
            # Return the templated post html
            return HttpResponse(post_html)
    # Error while parsing
    except:
        # 500 internal server error response
        return HttpResponse(status='500')

Edit:

I've ran some further testing on which specific browsers cause the same problem, and I ran into the conclusion that chrome desktop is the only browser that doesn't have this problem.

Use the @ensure_csrf_cookie decorator.

From docs :

Page uses AJAX without any HTML form¶

A page makes a POST request via AJAX, and the page does not have an HTML >form with a csrf_token that would cause the required CSRF cookie to be >sent.

Solution: use ensure_csrf_cookie() on the view that sends the page.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM