2

Can't figure this one out. The CSRF verification works fine in all my Django template views. Here I'm trying to post from a python client using techniques I've found in other posts. The client.get(url) call does provide the token (the debugger shows, for example: client.cookies['csrftoken'] = 'POqMV69MUPzey0nyLmifBglFDfBGDuo9') but requests.post() fails with error 403, CSRF verification failed. What's going on?

My Django view (with some dummy stuff in the methods):

class CameraUpload(View):
    template_name = "account/templates/upload.html"

    def get(self, request):
        dummy = VideoForm()
        return render(request, self.template_name, {'form': dummy})

    def post(self, request):
        dummy = VideoForm()
        return render(request, self.template_name, {'form': dummy})

And the client that's trying to do the post:

import requests

url = 'http://127.0.0.1:8000/account/camera_upload/'

client = requests.session()
client.get(url)
csrftoken = client.cookies['csrftoken']

payload = {
    'csrfmiddlewaretoken': csrftoken,
    'tag': '69'
}

r = requests.post(url, data=payload)

EDIT:

Tried adding the referer as per this link so code now looks like:

r = requests.post(url, data=payload, headers=dict(Referer=url))

but same problem exists.

wizzwizz4
  • 6,140
  • 2
  • 26
  • 62
Gadzooks34
  • 1,718
  • 2
  • 20
  • 29
  • you have an extra foreword slash in your url aka `/` you should probably remove that – John Ruddell Jun 10 '15 at 16:32
  • That slash needs to be there. Removing it results in the following error: "You called this URL via POST, but the URL doesn't end in a slash and you have APPEND_SLASH set. Django can't redirect to the slash URL while maintaining POST data..." – Gadzooks34 Jun 10 '15 at 16:40
  • well then the next question would be why do you have `APPEND_SLASH` set? an additional slash usually can mess things up especially on the front end (javascript etc.).. but I guess since you have it as a setting its ok? might not be the best practice though. my guess as to what is wrong is everytime you make a request its setting a cookie / certificate so sending the one from a previous request is messing up the next request.. but I don't know with what is provided.. – John Ruddell Jun 10 '15 at 16:42
  • I think I missed your comment before posting my edit but that's exactly right. Thanks. – Gadzooks34 Jun 10 '15 at 17:34

1 Answers1

6

You should be using your session (client) for the post:

r = client.post(url, data=payload, headers=dict(Referer=url))
dgel
  • 16,352
  • 8
  • 58
  • 75