使用python请求传递csrftoken

时间:2012-11-26 15:04:29

标签: python csrf python-requests

如何使用python模块请求传递csrftoken?这就是我所拥有的,但它不起作用,我不确定将它传入哪个参数(数据,标题,认证...)

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

每次都有相同的错误消息。

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

2 个答案:

答案 0 :(得分:73)

如果您要设置引荐来源标头,那么对于该特定网站,您需要将引荐来源设置为与登录页面相同的URL:

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

使用不安全的http时,Referer标头通常会被过滤掉,否则很容易被欺骗,因此大多数网站不再需要设置标头。但是,在使用SSL连接时,如果已设置,则站点确实有意义至少引用逻辑上已启动请求的内容。 Django在加密连接时使用https://),然后主动要求它。

答案 1 :(得分:1)

同样,使用 django 的csrf_client 注意,主要区别在于使用了login_data中的csrftoken.value 。用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))