개발/Python

파이썬 요청으로 csrftoken 전달

MinorMan 2020. 10. 2. 02:11
반응형

<질문>

파이썬 모듈 요청과 함께 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"})

매번 동일한 오류 메시지.

Forbidden (403)

CSRF verification failed. Request aborted.


<답변1>

리퍼러 헤더를 설정하려면 해당 특정 사이트에 대해 리퍼러를 로그인 페이지와 동일한 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 : // 사용)이 작업을 수행하고 적극적으로 필요합니다.


<답변2>

마찬가지로 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))
반응형