How do you pass a csrftoken with the python module Requests? This is what I have but it’s not working, and I’m not sure which parameter to pass it into (data, headers, auth…)
import requests
from bs4 import BeautifulSoup
URL = 'https://portal.bitcasa.com/login'
client = requests.session(config={'verbose': sys.stderr})
# Retrieve the CSRF token first
soup = BeautifulSoup(client.get('https://portal.bitcasa.com/login').content)
csrftoken = soup.find('input', dict(name='csrfmiddlewaretoken'))['value']
login_data = dict(username=EMAIL, password=PASSWORD, csrfmiddlewaretoken=csrftoken)
r = client.post(URL, data=login_data, headers={"Referer": "foo"})
Same error message every time.
<h1>Forbidden <span>(403)</span></h1> <p>CSRF verification failed. Request aborted.</p>
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
If you are going to set the referrer header, then for that specific site you need to set the referrer to the same URL as the login page:
import sys
import requests
URL = 'https://portal.bitcasa.com/login'
client = requests.session()
# Retrieve the CSRF token first
client.get(URL) # sets cookie
if 'csrftoken' in client.cookies:
# Django 1.6 and up
csrftoken = client.cookies['csrftoken']
else:
# older versions
csrftoken = client.cookies['csrf']
login_data = dict(username=EMAIL, password=PASSWORD, csrfmiddlewaretoken=csrftoken, next='/')
r = client.post(URL, data=login_data, headers=dict(Referer=URL))
When using unsecured http, the Referer header is often filtered out and otherwise easily spoofable anyway, so most sites no longer require the header to be set. However, when using an SSL connection and if it is set, it does make sense for the site to validate that it at least references something that could logically have initiated the request. Django does this when the connection is encrypted (uses https://), and actively requires it then.
Method 2
Similarly, using django‘s csrf_client note the primary difference is using csrftoken.value in the login_data. Tested with Django 1.10.5 —
import sys import django from django.middleware.csrf import CsrfViewMiddleware, get_token from django.test import Client django.setup() csrf_client = Client(enforce_csrf_checks=True) URL = 'http://127.0.0.1/auth/login' EMAIL= '<a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="1b6f7e686f366e687e695b6f7e686f35787476">[email protected]</a>' PASSWORD= 'XXXX' # Retrieve the CSRF token first csrf_client.get(URL) # sets cookie csrftoken = csrf_client.cookies['csrftoken'] login_data = dict(username=EMAIL, password=PASSWORD, csrfmiddlewaretoken=csrftoken.value, next='/') r = csrf_client.post(URL, data=login_data, headers=dict(Referer=URL))
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0