urllib2 基本认证问题

8 投票
4 回答
6414 浏览
提问于 2025-04-16 11:08

我真是头疼不已,遇到这个问题让我很沮丧。我尝试了各种例子,网上能找到的关于使用urllib2进行基本http授权的资料我都看了,但就是搞不清楚我遇到的具体错误是什么。

更让人烦恼的是,这段代码在一个页面上能正常工作,但在另一个页面上却不行。登录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>

在谷歌上搜索这个错误,完全没有找到相关的信息。

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 个回答

1

从你发布的HTML来看,我觉得你在认证时是成功的,但在处理你的POST请求时遇到了错误。我试了你的网址,认证失败时,我得到了一个标准的401页面。

无论如何,我建议你再试一次,运行你的代码,并在Firefox中手动执行相同的操作,这次用Wireshark来捕捉数据交换。你可以在这两种情况下抓取HTTP请求和响应的完整文本,然后对比一下差异。大多数情况下,这样能帮助你找到错误的源头。

4

今天遇到了类似的问题。我在开发的网站上使用了基本认证,但无法验证任何用户。

这里有一些可以帮助你排查问题的建议:

  1. 我使用了 slumber.inhttplib2 来进行测试。我在 ipython shell 中运行这两个工具,看看我收到了什么响应。
  2. Slumber 实际上是在底层使用 httplib2,所以它们的表现很相似。我使用了 tcpdump,后来又用了 tcpflow(这个工具显示的信息更易读)来查看实际发送和接收的数据。如果你想要图形界面的工具,可以试试 wireshark 或其他类似的工具。
  3. 我用 curl 测试了我的网站,当我用用户名和密码运行 curl 时,它正常工作并显示了请求的页面。但 slumber 和 httplib2 还是不行。
  4. 我测试了我的网站和 browserspy.dk,想看看有什么不同。重要的是,browserspy 的网站支持基本认证,而我的网站不支持,所以我可以进行对比。我在很多地方看到需要发送 HTTP 401 未授权状态,这样浏览器或你使用的工具才能发送你提供的用户名和密码。但我不知道的是,头信息中还需要有 WWW-Authenticate 字段。这就是我缺失的部分。
  5. 这整个情况的奇怪之处在于,在测试时,我看到 httplib2 在大多数请求中发送了基本认证的头信息(tcpflow 会显示这一点)。结果发现,这个库在第一次请求时并不会发送用户名和密码的认证信息。如果响应中有“状态 401”和“WWW-Authenticate”,那么凭据会在第二次请求时发送,并且从那以后对这个域的所有请求都会发送凭据。

所以总结一下,你的应用可能是正确的,但你可能没有返回标准的头信息和状态码,导致客户端无法发送凭据。使用你的调试工具找出问题所在。此外,httplib2 还有调试模式,只需设置 httplib2.debuglevel=1,这样调试信息就会打印到标准输出。这比使用 tcpdump 更有帮助,因为它处于更高的层次。

希望这对某些人有帮助。

2

大约一年前,我经历了同样的过程,并记录了我解决这个问题的方法——有一种直接简单的认证方式,还有一种标准的方式。你可以选择你觉得合适的。

Python中的HTTP认证

在这个缺失的urllib2文档中,有详细的说明。

撰写回答