python-requests and django - CSRF verification failed. Request aborted

user2040597 picture user2040597 · Nov 27, 2013 · Viewed 7.7k times · Source

I have a django server to upload files and when I use a browser, I can upload the file without problems.

But if I use the python-requests commands, it tells me CSRF verification failed. Request aborted. The python-requests code is as followed:

    # upload via HTTP
    file = {"docfile": open(fullfilename, "rb")}
    s = requests.Session()
    r = s.get(dhost)
    r = s.post(dhost, files=file)

If I execute my code, I get the code 403 and the error CSRF verification failed. Request aborted. Reason given for failure:

CSRF token missing or incorrect.

But if I look in the header I sent, I have the cookie set:

CaseInsensitiveDict({'Content-Length': u'84169', 
'Accept-Encoding': 'gzip, deflate, compress', 
'Accept': '*/*', 
'User-Agent': 'python-requests/2.0.1 CPython/2.7.3 Linux/3.6.11+', 
'Cookie': 'csrftoken=GOOIsG89i5oMCJO6594algTXooxoUeoL', 
'Content-Type': 'multipart/form-data; boundary=86ada00b4f6c41d5997293cce7a53b6b'})

Could you please tell me what I should do in order to have this to work?

Answer

yuvi picture yuvi · Nov 27, 2013

It's actually all working fine, you just have to understand how csrf works. When you load the page in your browser, you get a csrf token inside {% csrf_token %}, So when you send the data to the server, you also send along the csrf token.

When you use requests, you're getting the cookie in the 'get' part, but you're not sending it along with your 'post'. without it, you're just sending a post request with no token at all, which means a CSRF verification error. To solve it, try this code:

file = {"docfile": open(fullfilename, "rb")}
s = requests.Session()
r1 = s.get(dhost)
csrf_token = r1.cookies['csrftoken']
r2 = s.post(dhost, files=file, data={'csrfmiddlewaretoken': csrf_token}, headers=dict(Referer=dhost))

If this is just for your own usage, you can disable csrf on that view using csrf_exampt:

@csrf_exempt
def my_view(request):
   ...whateva...

But note that this isn't a recommended solution if you plan to launch your server and open it to the public