web-dev-qa-db-fra.com

Passer csrftoken avec python Requests

Comment passer un csrftoken avec les requêtes du module python? C'est ce que j'ai mais cela ne fonctionne pas, et je ne sais pas dans quel paramètre le passer (données, en-têtes, 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"})

Même message d'erreur à chaque fois.

<h1>Forbidden <span>(403)</span></h1>
<p>CSRF verification failed. Request aborted.</p>
42
Jeff

Si vous allez définir l'en-tête du référent, alors pour ce site spécifique, vous devez définir le référent sur la même URL que la page de connexion:

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))

Lorsque vous utilisez http non sécurisé, l'en-tête Referer est souvent filtré et autrement facilement usurpé de toute façon, de sorte que la plupart des sites n'ont plus besoin de définir l'en-tête. Cependant, lors de l'utilisation d'une connexion SSL et si elle est définie, il est logique que le site valide qu'il fait au moins référence à quelque chose qui aurait logiquement pu lancer la demande. Django fait cela lorsque la connexion est cryptée (utilise https://), et l'exige alors activement.

78
Martijn Pieters

De même, en utilisant Django le csrf_client notez que la principale différence est d'utiliser csrftoken.value dans le login_data. Testé avec 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= '[email protected]'
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))
2
storm_m2138