oddites базовой аутентификации urllib2 - PullRequest
8 голосов
/ 03 февраля 2011

Я ударю головой об стену с этим.Я пробовал каждый пример, читая каждый последний бит, который я могу найти в Интернете о базовой http-авторизации с помощью urllib2, но я не могу понять, что является причиной моей конкретной ошибки.

К разочарованию добавляется то, что код работает для одной страницы, но не для другой.вход на www.mysite.com/adm проходит абсолютно гладко.Это подтверждает подлинность без проблем.Тем не менее, если я изменю адрес на 'http://mysite.com/adm/items.php?n=201105&c=200', я получу эту ошибку:

<h4 align="center" class="teal">Add/Edit Items</h4>
<p><strong>Client:</strong> </p><p><strong>Event:</strong> </p><p class="error">Not enough information to complete this task</p>

<p class="error">This is a fatal error so I am exiting now.</p>

Поиск в Google привел к нулевой информации об этой ошибке.

adm - это страница с набором фреймов, я не уверен, что это вообще актуально.

Вот текущий код:

import urllib2, urllib
import sys

import re
import base64
from urlparse import urlparse

theurl = 'http://xxxxxmedia.com/adm/items.php?n=201105&c=200'
username = 'XXXX'
password = 'XXXX'

passman = urllib2.HTTPPasswordMgrWithDefaultRealm()
passman.add_password(None, theurl,username,password)

authhandler = urllib2.HTTPBasicAuthHandler(passman)

opener = urllib2.build_opener(authhandler)

urllib2.install_opener(opener)

pagehandle = urllib2.urlopen(theurl)

url = 'http://xxxxxxxmedia.com/adm/items.php?n=201105&c=200'
values = {'AvAudioCD': 1,
          'AvAudioCDDiscount': 00, 'AvAudioCDPrice': 50,
          'ProductName': 'python test', 'frmSubmit': 'Submit' }

#opener2 = urllib2.build_opener(urllib2.HTTPCookieProcessor())
data = urllib.urlencode(values)
req = urllib2.Request(url, data)
response = urllib2.urlopen(req)

Это только одна из многих версий, которые я пробовал.Я следовал каждому примеру из Urllib2 Missing Manual, но все равно получаю ту же ошибку.

Кто-нибудь может указать на то, что я делаю неправильно?

Ответы [ 4 ]

4 голосов
/ 13 октября 2011

столкнуться с подобной проблемой сегодня. Я использовал базовую аутентификацию на веб-сайте, который я разрабатываю, и я не мог аутентифицировать пользователей.

Вот несколько вещей, которые вы можете использовать для отладки вашей проблемы:

  1. Я использовал slumber.in и httplib2 для тестирования. Я запустил оба из оболочки ipython, чтобы посмотреть, какие ответы я получал.
  2. Сон фактически использует httplib2 под одеялами, поэтому они действовали аналогично. Я использовал tcpdump и более поздний tcpflow (который показывает информацию в гораздо более удобочитаемой форме), чтобы увидеть, что на самом деле отправлялось и получалось. Если вам нужен графический интерфейс, см. Wireshark или альтернативные варианты.
  3. Я протестировал свой веб-сайт с помощью curl, и когда я использовал curl с моим именем пользователя и паролем, он работал правильно и показывал запрашиваемую страницу. Но сон и httplib2 все еще не работали.
  4. Я проверил свой веб-сайт и browserspy.dk , чтобы увидеть, в чем заключаются различия. Важно то, что веб-сайт browserspy работает для базовой аутентификации, а мой веб-сайт - нет, поэтому я мог сравнить их. Я читал во многих местах, что вам нужно отправить HTTP 401 Not Authorized, чтобы браузер или инструмент, который вы используете, могли отправить имя пользователя / пароль, которые вы указали. Но я не знал, что вам также нужно поле WWW-Authenticate в заголовке. Так что это был недостающий кусок.
  5. Что сделало всю эту ситуацию странной, так это то, что во время тестирования я увидел, что httplib2 отправляет заголовки базовой аутентификации с большинством запросов (tcpflow покажет это). Оказывается, библиотека не отправляет аутентификацию по имени пользователя / паролю при первом запросе. Если в ответе указано «Status 401» И «WWW-Authenticate», учетные данные отправляются по второму запросу, а затем все запросы к этому домену.

Итак, подведем итог: ваше приложение может быть правильным, но вы, возможно, не возвращаете стандартные заголовки и код состояния, чтобы клиент отправлял учетные данные. Используйте ваши инструменты отладки, чтобы найти что есть что. Кроме того, есть режим отладки для httplib2, просто установите httplib2.debuglevel=1, чтобы отладочная информация выводилась на стандартный вывод. Это гораздо полезнее, чем использование tcpdump, потому что он на более высоком уровне.

Надеюсь, это кому-нибудь поможет.

2 голосов
/ 03 февраля 2011

Примерно год назад я прошел тот же процесс и задокументировал, как я решил проблему - прямой и простой способ аутентификации и стандартный. Выберите то, что вы считаете нужным.

HTTP-аутентификация в Python

В документе отсутствует urllib2 * есть объясненное описание .

1 голос
/ 03 февраля 2011

Исходя из размещенного вами HTML-кода, он по-прежнему считает, что вы успешно прошли аутентификацию, но впоследствии столкнулись с ошибкой при обработке вашего запроса POST.Я попробовал ваш URL и не прошел аутентификацию, я получил стандартную страницу 401.

В любом случае я предлагаю вам попробовать еще раз запустить свой код и выполнить ту же самую операцию вручную в Firefox, только на этот раз с Wireshark для захвата обмена.Вы можете получить полный текст HTTP-запроса и ответа в обоих случаях и сравнить различия.В большинстве случаев это приведет вас к источнику ошибки, которую вы получите.

0 голосов
/ 19 января 2017

Я также обнаружил, что материал для паролей не работает (иногда?).Добавление заголовка user / pass base64 согласно этому ответу https://stackoverflow.com/a/18592800/623159 сработало для меня.Я получаю доступ к URL-адресу jenkins следующим образом: http: /// job // lastCompletedBuild / testR‌ ‌ eport / api / python

Это работает для меня:

import urllib2
import base64

baseurl="http://jenkinsurl"
username=...
password=...

url="%s/job/jobname/lastCompletedBuild/testReport/api/python" % baseurl

base64string = base64.encodestring('%s:%s' % (username, password)).replace('\n', '')
request = urllib2.Request(url)
request.add_header("Authorization", "Basic %s" % base64string) 
result = urllib2.urlopen(request)
data = result.read()

Это не 'у меня не работает, ошибка 403 каждый раз:

import urllib2

baseurl="http://jenkinsurl"
username=...
password=...

##urllib2.HTTPError: HTTP Error 403: Forbidden
passman = urllib2.HTTPPasswordMgrWithDefaultRealm()
passman.add_password(None, url, username,password)
urllib2.install_opener(urllib2.build_opener(urllib2.HTTPBasicAuthHandler(passman)))
req = urllib2.Request(url)
result = urllib2.urlopen(req)
data = result.read()
...