Passer csrftoken avec des requêtes python

Comment passer un csrftoken avec les requêtes du module python? C'est ce que j'ai mais ça ne marche 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>
38
demandé sur Jeff 2012-11-26 19:04:28

2 réponses

si vous voulez définir l'en-tête referrer, alors pour ce site spécifique vous devez définir le referrer à 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))

lors de l'utilisation de http, le Referer l'en-tête est souvent filtré et de toute façon facilement spoofable, de sorte que la plupart des sites n'ont plus besoin de l'en-tête à définir. Cependant, lors de l'utilisation D'une connexion SSL et si elle est définie, il est logique pour le site de valider qu'il renvoie au moins quelque chose qui pourrait logiquement ont initié la demande. Django fait cela quand la connexion est cryptée (utilise https://), et l'exige activement alors.

63
répondu Martijn Pieters 2018-08-12 12:31:05

de même, en utilisant django's csrf_client notez que la principale différence est l'utilisation de csrftoken.valeur 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= 'test-user@test.com'
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))
1
répondu storm_m2138 2017-08-04 22:54:52