Запросы Python — аутентификация после перенаправления

python #python-2.7 #python-requests

#python #аутентификация #перенаправление #python-запросы

Вопрос:

У меня есть быстрый вопрос относительно базовой аутентификации HTTP после перенаправления.

Я пытаюсь войти на веб-сайт, который по оперативным соображениям немедленно перенаправляет меня на центральный сайт входа, используя ответ HTTP 302. В моем тестировании кажется, что модуль запросов не отправляет мои учетные данные на центральный сайт входа после перенаправления. Как видно из приведенного ниже фрагмента кода, я вынужден извлечь URL-адрес перенаправления из объекта ответа и повторить попытку входа в систему.

Мой вопрос прост:
есть ли способ принудительно отправлять запросы на повторную отправку учетных данных для входа после перенаправления вне хоста?

По соображениям переносимости я бы предпочел не использовать файл .netrc. Кроме того, поставщик веб-сайта сделал url_login статическим, но не сделал такого заявления о url_redirect.

Спасибо за ваше время!

ФРАГМЕНТ КОДА

 import requests

url_login = '<url_login>'
myauth = ('<username>', '<password')

login1 = requests.request('get', url_login, auth=myauth)
# this login fails; response object contains the login form information

url_redirect = login1.url
login2 = requests.request('get', url_redirect, auth=myauth)
# this login succeeds; response object contains a welcome message
 

Обновить

Вот более конкретная версия общего кода выше.

  • Первый request() возвращает ответ HTTP 200 и содержит информацию о форме в текстовом поле.
  • Второй request() возвращает ответ HTTP 401 с 'HTTP Basic: Access denied.' в его текстовом поле.

(Конечно, вход в систему выполняется успешно, если предоставлены действительные учетные данные.)

Опять же, мне интересно, смогу ли я достичь желаемого входа в систему только одним вызовом requests.request() .

 import requests

url_login = 'http://cddis-basin.gsfc.nasa.gov/CDDIS_FileUpload/login' 
myauth = ('<username>', '<password>') 

with requests.session() as s: 
    login1 = s.request('get', url_login, auth=myauth) 
    url_earthdata = login1.url 
    login2 = s.request('get', url_earthdata, auth=myauth)
 

Комментарии:

1. Можете ли вы поделиться URL-адресом?

2. Конечно, URL- адрес cddis-basin.gsfc.nasa.gov/CDDIS_FileUpload/login , и более подробную информацию о том, что я пытаюсь сделать, можно найти по адресу cddis.gsfc.nasa.gov/Data_and_Derived_Products /. … Я хотел, чтобы мой вопрос был как можно более общим, но если это поможет, продолжайте!

3. Я думаю, вам нужен сеанс, вы пытаетесь имитировать логику curl?

4. Да, я пытаюсь имитировать логику cURL. В моей собственной реализации я использую сеанс для обработки файлов cookie. Однако конкретная проблема, о которой я интересуюсь (сбой аутентификации после повторного перенаправления), не зависит от использования объекта сеанса.

Ответ №1:

Моим решением для этого было бы использование «Сеанса». Вот как вы можете реализовать сеанс.

 import requests

s = requests.session()
url_login = "<loginUrl>"

payload = {
    "username": "<user>",
    "password": "<pass>"
}

req1 = s.post(url_login, data=payload)

# Now to make sure you do not get the "Access denied", use the same session variable for the request.

req2 = s.get(url_earthdata)
 

Это должно решить вашу проблему.

Комментарии:

1. Спасибо, что порекомендовали использовать сеанс — я соответствующим образом обновил пример кода в своем сообщении. К сожалению, URL-адрес, на который вы ссылаетесь в своей второй команде, url_earthdata , заранее неизвестен. URL, указанный для входа в систему, url_login , возвращает перенаправление HTTP 302 на адрес, который не гарантированно будет статическим. Я хотел бы отправить свои учетные данные на второй URL-адрес без явного извлечения URL-адреса с первой попытки ( url_earthdata = login1.url ) и выполнения второй попытки ( login2 = s.request('get', url_earthdata, auth=myauth) )

2. в этом случае вы можете использовать «allow_redirects = False» в первом запросе, чтобы получить перенаправляющий URL. Просто просмотрите заголовки первого запроса для «url_earthdata», который вы ищете. Например, >>> req1 = s.post(url_login, data=полезная нагрузка, allow_redirects=False) >>> url_earthdata = req1.headers[«<URL_KEY>»]

3. Хорошо, это хороший совет, но для этого все равно требуется два отдельных HTTP-запроса. Поскольку я хотел узнать больше о повторной отправке учетных данных для входа после перенаправления вне хоста — т. Е. Для достижения моего входа в систему только с помощью одного запроса — я могу принять этот ответ, если вы отвлекаете внимание от сеансов и вместо этого подчеркиваете, что «нет, вы не можете сделать это в одном запросе». Спасибо за ваше время!

4. Целью HTTP 302 является перенаправление URL . Ответ с кодом состояния 302 предоставляет URL-адрес перенаправления в его заголовке под ключом местоположения , который должен быть запущен при выполнении другого запроса . Итак, нет , вы не можете достичь того, что пытаетесь, с помощью одного запроса .

Ответ №2:

Это невозможно с запросами по дизайну. Проблема связана с уязвимостью в системе безопасности, когда, если злоумышленник изменяет URL-адрес перенаправления, и учетные данные автоматически отправляются на URL-адрес перенаправления, учетные данные оказываются скомпрометированными. Таким образом, учетные данные удаляются из вызовов перенаправления.

На github есть тема об этом: https://github.com/psf/requests/issues/2949