Python запрашивает POST с заголовком и параметрами - PullRequest
0 голосов
/ 01 июля 2018

У меня есть почтовый запрос, который я пытаюсь отправить, используя requests в python. Но я получаю неверную ошибку 403. Запросы отлично работают через браузер.

POST /ajax-load-system HTTP/1.1
Host: xyz.website.com
Accept: application/json, text/javascript, */*; q=0.01
Accept-Language: en-GB,en;q=0.5
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/60.0
Referer: http://xyz.website.com/help-me/ZYc5Yn
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
X-Requested-With: XMLHttpRequest
Content-Length: 56
Cookie: csrf_cookie_name=a3f8adecbf11e29c006d9817be96e8d4; ci_session=ba92hlh6o0ns7f20t4bsgjt0uqfdmdtl; _ga=GA1.2.1535910352.1530452604; _gid=GA1.2.1416631165.1530452604; _gat_gtag_UA_21820217_30=1
Connection: close

csrf_test_name=a3f8adecbf11e29c006d9817be96e8d4&vID=9999

В Python я пытаюсь:

import requests
import json

url = 'http://xyz.website.com/ajax-load-system'

payload = {
'Host': 'xyz.website.com',
'User-Agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/60.0',
'Accept': 'application/json, text/javascript, */*; q=0.01',
'Accept-Language': 'en-GB,en;q=0.5',
'Referer': 'http://xyz.website.com/help-me/ZYc5Yn',
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
'X-Requested-With': 'XMLHttpRequest',
'Content-Length': '56',
'Cookie': 'csrf_cookie_name=a3f8adecbf11e29c006d9817be96e8d4; ci_session=ba92hlh6o0ns7f20t4bsgjt0uqfdmdtl; _ga=GA1.2.1535910352.1530452604; _gid=GA1.2.1416631165.1530452604; _gat_gtag_UA_21820217_30=1',
'Connection': 'close',
'csrf_test_name': 'a3f8adecbf11e29c006d9817be96e8d4',
'vID': '9999',
}    

headers = {}

r = requests.post(url, headers=headers, data=json.dumps(payload))
print(r.status_code)  

Но это печать кода ошибки 403. Что я здесь не так делаю?

Я ожидаю ответного ответа в виде json:

{"status_message":"Thanks for help.","help_count":"141","status":true}

1 Ответ

0 голосов
/ 01 июля 2018

Вы путаете заголовки и полезную нагрузку, а полезная нагрузка не закодирована в JSON .

Это все заголовки:

Host: xyz.website.com
Accept: application/json, text/javascript, */*; q=0.01
Accept-Language: en-GB,en;q=0.5
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/60.0
Referer: http://xyz.website.com/help-me/ZYc5Yn
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
X-Requested-With: XMLHttpRequest
Content-Length: 56
Cookie: csrf_cookie_name=a3f8adecbf11e29c006d9817be96e8d4; ci_session=ba92hlh6o0ns7f20t4bsgjt0uqfdmdtl; _ga=GA1.2.1535910352.1530452604; _gid=GA1.2.1416631165.1530452604; _gat_gtag_UA_21820217_30=1
Connection: close

Большинство из них автоматизированы и не требуют настройки вручную. requests будет устанавливать Host для вас на основе URL, Accept устанавливается на приемлемое значение по умолчанию, Accept-Language редко требуется в этих ситуациях, Referer, если только не используется HTTPS, часто даже не устанавливается и не фильтруется из соображений конфиденциальности, поэтому сайты больше не полагаются на его установку, Content-Type должен фактически отражать содержимое вашего POST (и не является JSON!), поэтому requests устанавливает это для вас в зависимости от того, как вы его называете , Content-Length должен отражать фактическую длину содержимого, поэтому устанавливается requests, так как он находится в лучшем положении для вычисления этого, и Connection определенно должен обрабатываться библиотекой, так как вы не хотите, чтобы это препятствовало эффективно повторно использовать соединения, если это возможно.

В лучшем случае вы можете установить X-Requested-With и User-Agent, но только если сервер иначе не примет запрос. Заголовок Cookies отражает значения файлов cookie, хранящихся в браузере. Ваш сценарий может получить свой собственный набор файлов cookie с сервера, используя объект сеанса запросов , чтобы сделать первоначальный запрос GET к URL-адресу, указанному в заголовке Referer (или другому подходящему URL-адресу на том же сайт), после чего сервер должен установить куки в ответе, и они будут сохранены в сеансе для повторного использования по запросу пост. Используйте этот механизм, чтобы получить собственное значение файла cookie CSRF.

Обратите внимание на заголовок Content-Type:

Content-Type: application/x-www-form-urlencoded; charset=UTF-8

Когда вы передаете словарь в ключевое слово data функции requests.post(), библиотека закодирует данные именно для этого типа контента.

Фактическая полезная нагрузка составляет

csrf_test_name=a3f8adecbf11e29c006d9817be96e8d4&vID=9999

Это два поля, csrf_test_name и vID, которые должны входить в ваш словарь payload.

Обратите внимание, что значение csrf_test_name соответствует значению csrf_cookie_name в файлах cookie . Таким образом сайт защищается от межсайтовых фальсификаций , когда третье лицо может попытаться опубликовать по тому же URL-адресу от вашего имени. Такая третья сторона не будет иметь доступа к тем же файлам cookie, поэтому будет предотвращена. Ваш код должен получить новый файл cookie ; правильная реализация CSRF ограничит время повторного использования любого файла CSRF.

Итак, что нужно , по крайней мере, , чтобы все это заработало:

# *optional*, the site may not care about these. If they *do* care, then
# they care about keeping out automated scripts and could in future 
# raise the stakes and require more 'browser-like' markers. Ask yourself
# if you want to anger the site owners and get into an arms race.
headers = {
    'User-Agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/60.0',
    'X-Requested-With': 'XMLHttpRequest',
}

payload = {
    'vID': 9999,
}

url = 'http://xyz.website.com/ajax-load-system'
# the URL from the Referer header, but others at the site would probably
# also work
initial_url = 'http://xyz.website.com/help-me/ZYc5Yn'

with requests.Session() as session:
    # obtain CSRF cookie
    initial_response  = session.get(initial_url)
    payload['csrf_test_name'] = session.cookies['csrf_cookie_name']

    # Now actually post with the correct CSRF cookie
    response = session.post(url, headers=headers, data=payload)

Если это все еще вызывает проблемы, вам нужно попробовать два дополнительных заголовка, Accept и Accept-Language. Учтите, что это будет означать, что сайт уже давно и много думал о том, как сохранить автоматические скребки для сайтов out . Вы можете связаться с ними и спросить, предлагают ли они вместо этого API-интерфейс.

...