Django returns 403 error when sending a POST request
Asked Answered
R

7

53

when I'm using following Python code to send a POST request to my Django website I'm getting 403: Forbidden error.

url = 'http://www.sub.example.com/'
values = { 'var': 'test' }

try:
    data = urllib.urlencode(values, doseq=True)
    req = urllib2.Request(url, data)
    response = urllib2.urlopen(req)
    the_page = response.read()
except:
    the_page = sys.exc_info()
    raise

When I'm opening any other website it works properly. example.com is Django website too, and it works properly too. I think, that's Django config problem, can anyone tell me what should I do to provide access to my script?

Recitativo answered 23/7, 2011 at 14:4 Comment(4)
Can you get to the webpage from a normal web browser?Cedillo
I can get from normal browser. My server logs are empty, I do not have sufficient piriveges to view all of them on my hosting.Recitativo
https://mcmap.net/q/340700/-403-forbidden-error-when-making-an-ajax-post-request-in-django-frameworkOutmoded
In DRF, including permission_classes in view worked. eg: permission_classes = [permissions.IsAuthenticated]Prognostic
D
36

Does the view that you are posting to have a Django Form on it? If so, I wonder if it's giving a csrf error. I think that manifests itself as a 403. In that case, you'd need to add the {{ csrf_token }} tag. Just a thought.

Disincentive answered 23/7, 2011 at 14:58 Comment(5)
Where have I to add that tag? If in template - it doesn't work. Here's my view: dpaste.com/575405, t.html is simply {{ form }}Recitativo
can you update the original question to inclue your code(view, urls, form) and html instead of linking off to dpaste?Cedillo
@Recitativo why is t.html only a {{form}} is it included into other pages? if you just put {{form}} it isn't a valid webpage, and not even a valid form since {{form}} just puts the form elements you still need to add the form tags around it.Cedillo
If it is a csrf problem you can try to disable csrf temporarliy on the view and see if that works, and if so then you know what the issue is. see this documentation for more help. docs.djangoproject.com/en/1.3/ref/contrib/csrf/#exceptionsCedillo
Correct answer.Finkle
B
52

Look here https://docs.djangoproject.com/en/dev/ref/csrf/#how-to-use-it.

Try marking your view with @csrf_exempt. That way, Django's CSRF middleware will ignore CSRF protection. You'll also need to use from django.views.decorators.csrf import csrf_exempt. See: https://docs.djangoproject.com/en/dev/ref/csrf/#utilities

Please be advised that by disabling CSRF protection on your view, you are opening a gate for CSRF attacks.

If security is vital to you then consider using @csrf_exempt followed by @requires_csrf_token (see: https://docs.djangoproject.com/en/dev/ref/csrf/#unprotected-view-needs-the-csrf-token). Then, in your script pass this token and that's it.

Britteny answered 23/7, 2011 at 15:37 Comment(1)
Thank you so very much for sharing above two links. My code is running perfectly fine after adding this import statement from django.views.decorators.csrf import csrf_protect and after making specific function exempted like this @csrf_exempt Once again thanks alot.Follett
D
36

Does the view that you are posting to have a Django Form on it? If so, I wonder if it's giving a csrf error. I think that manifests itself as a 403. In that case, you'd need to add the {{ csrf_token }} tag. Just a thought.

Disincentive answered 23/7, 2011 at 14:58 Comment(5)
Where have I to add that tag? If in template - it doesn't work. Here's my view: dpaste.com/575405, t.html is simply {{ form }}Recitativo
can you update the original question to inclue your code(view, urls, form) and html instead of linking off to dpaste?Cedillo
@Recitativo why is t.html only a {{form}} is it included into other pages? if you just put {{form}} it isn't a valid webpage, and not even a valid form since {{form}} just puts the form elements you still need to add the form tags around it.Cedillo
If it is a csrf problem you can try to disable csrf temporarliy on the view and see if that works, and if so then you know what the issue is. see this documentation for more help. docs.djangoproject.com/en/1.3/ref/contrib/csrf/#exceptionsCedillo
Correct answer.Finkle
A
3

The response is 403 because django requires a csrf token (included in the post data) in every POST request you make.

There are various ways to do this such as:

Acquiring the token from cookie and the method has been explained in article enter link description here

or

You can access it from DOM using {{ csrf_token }}, available in the template

So now using the second method:

var post_data = {
  ...
  'csrfmiddlewaretoken':"{{ csrf_token }}"
  ...
}

$.ajax({
  url:'url',
  type:'POST'
  data:post_data,
  success:function(data){
    console.log(data);
  },
  error:function(error){
    console.log(error);
  }
});
Actinochemistry answered 19/6, 2016 at 15:30 Comment(0)
C
3

Or you can allow the permission to make this post request.

Note: Should be used in the cases where you don't need to authenticate the users for posting anything on our server, say, when a new user registers for the first time.

from rest_framework.permissions import AllowAny

class CreateUser(APIView):
    permission_classes = (AllowAny,)
    def post(self, request, format=None):
        return(Response("hi"))

Further Note that, If you want to make that post request form a different domain (in case when the front of the application is in React or angular and the backend is in Django), make sure the add following in the settings file:

  1. Update the INSTALLED_APPS to use 'coreHeaders' :

    INSTALLED_APPS = [
    'corsheaders',
    ]

  2. White list your front end domain by adding following to settings file again:

    CORS_ORIGIN_WHITELIST = ( 'localhost:8080', )

Cabalist answered 7/6, 2017 at 14:37 Comment(0)
T
1

Django documentation provides several ways to ensure that CSRF tokens are included. See https://docs.djangoproject.com/en/1.11/ref/csrf/ for details.

Torrent answered 18/7, 2017 at 15:59 Comment(0)
A
1

I got this error when an authentication Token was expired or when no Token was sent with the request. Using a renewed token fixed the problem.

curl -X POST -H "Authorization: Token mytoken" -d "name=myname&age=0" 127.0.0.1:8000/myapi/

or

curl -X POST -H "Authorization: JWT mytoken" -d "name=myname&age=0" 127.0.0.1:8000/myapi/

depending on Token type.

Afroamerican answered 19/12, 2017 at 23:52 Comment(0)
C
0

I too had this problem, because I Tried to access the Main endpoint from another endpoint using '../url' URL Jumping. My Solution was to add another path for the same viewset;

router.register('main/url',ViewSet,'name');
router.register('secondary/url',ViewSet,'name')

But in Your Case You are Trying to access it from a completely different Location, From Django's Point of view So You need to mark you ViewSet with @crsf_exempt middleware which will Disable Security Protocols Related to CRSF.

Chromato answered 12/4, 2020 at 11:31 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.