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?
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.
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.
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
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')
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With