Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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?

like image 745
user2040597 Avatar asked Nov 27 '13 20:11

user2040597


People also ask

How do I fix CSRF verification failed aborted?

Are you trying to log in and are receiving a “Forbidden (403) CSRF verification failed.” message? What is happening is that our site's securities are in conflict with an autofill-enabled configuration in your browser. To fix, you can: Disable autofill, allow cookies, and clear your cache.

What is Csrf_exempt in Django?

This type of attack occurs when a malicious website contains a link, a form button or some JavaScript that is intended to perform some action on your website, using the credentials of a logged-in user who visits the malicious site in their browser.


2 Answers

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

like image 151
yuvi Avatar answered Sep 29 '22 03:09

yuvi


If I use the python-requests commands, it tells me CSRF verification failed. But if I look in the header I sent, I have the cookie set:

  '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

You have to send two things back to the server:

1) The csrftoken cookie.

2) The following form name/value pair:

"csrfmiddlewaretoken" = "csrf token here"

A requests session will take care of returning the cookie for you, but you have to add the form name/value pair:

sess = requests.Session()
r = sess.get(get_url)
my_csrf_token = r.cookies['csrftoken']

with open('myfile.txt') as f:
    r = sess.post(
        post_url,
        data = {
            "csrfmiddlewaretoken": my_csrf_token,
        },
        files = {"myfile": f}

)

print r.status_code
print r.text

When your django html template contains a csrf tag:

<form name="myMessage" 
      method="post" 
      class="signin" 
      action="/myapp/process_form/"
      enctype="multipart/form-data">

{% csrf_token %}

the csrf tag is replaced by a hidden form field:

<input type="hidden" 
       value="RTpun6OhlRehRRa2nAIcTtFJk5WuWsLg" 
       name="csrfmiddlewaretoken">

The hidden form field sends an additional name/value pair to the server along with all the other name/value pairs that the form creates. The name is "csrfmiddlewaretoken" and the value is the csrf token. django checks for the cookie as well as the name/value pair in the form data.

By the way, in order to get a csrf token for testing purposes, you can make a get request to a view that looks like this:

def myview(request):
    from django.middleware.csrf import get_token
    get_token(request)  #This causes django to set the csrftoken cookie in the response

    return HttpResponse('server received GET request')
like image 30
7stud Avatar answered Sep 29 '22 05:09

7stud