python - urllib2 HTTPPasswordMgr 不起作用 - 凭据未发送错误

标签 python curl urllib2 httplib

以下 python curl 调用具有以下成功结果:

>>> import subprocess
>>> args = [
        'curl',
        '-H', 'X-Requested-With: Demo',
        'https://username:<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="f181908282869e8395b18084909d8882908198df8084909d8882df929e9c" rel="noreferrer noopener nofollow">[email protected]</a>/qps/rest/3.0/count/was/webapp' ] 
>>> xml_output = subprocess.check_output(args).decode('utf-8')
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
138   276    0   276    0     0    190      0 --:--:--  0:00:01 --:--:--   315
>>> xml_output
u'<?xml version="1.0" encoding="UTF-8"?>\n<ServiceResponse xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://qualysapi.qualys.com/qps/xsd/3.0/was/webapp.xsd">\n<responseCode>SUCCESS</responseCode>\n  <count>33</count>\n</ServiceResponse>'

不幸的是,这个调用没有成功转换为 urllib2。我收到不同的 XML 响应,指出用户未提供授权凭据:

>>> import urllib2
>>> # Create a password manager.
... password_mgr = urllib2.HTTPPasswordMgrWithDefaultRealm()
>>> # Add the username and password.
... top_level_url = 'https://qualysapi.qualys.com'
>>> password_mgr.add_password(None, top_level_url, username, password)
>>> handler = urllib2.HTTPBasicAuthHandler(password_mgr)
>>> opener = urllib2.build_opener(handler)
>>> urllib2.install_opener(opener)
>>> headers = {'X-Requested-With':'Demo'}
>>> uri = 'https://qualysapi.qualys.com/qps/rest/3.0/count/was/webapp'
>>> req = urllib2.Request(uri,None,headers)
>>> result = urllib2.urlopen(req)
>>> result
'<ServiceResponse xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://qualysapi.qualys.com/qps/xsd/3.0/was/webapp.xsd">\n  <responseCode>INVALID_CREDENTIALS</responseCode>\n  <responseErrorDetails>\n    <errorMessage>User did not supply any authentication headers</errorMessage>\n  </responseErrorDetails>\n</ServiceResponse>'

顺便说一句,我收到与 httplib 相同的错误消息:

>>> import httplib, base64
>>> auth = 'Basic ' + string.strip(base64.encodestring(username + ':' + password))
>>> h = httplib.HTTPSConnection('qualysapi.qualys.com')
>>> h.request("GET", "/qps/rest/3.0/count/was/webapp/")
>>> r1 = h.getresponse()
>>> print r1.status, r1.reason
200 OK
>>> data1 = r1.read()
>>> data1
'<ServiceResponse xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://qualysapi.qualys.com/qps/xsd/3.0/was/webapp.xsd">\n  <responseCode>INVALID_CREDENTIALS</responseCode>\n  <responseErrorDetails>\n    <errorMessage>User did not supply any authentication headers</errorMessage>\n  </responseErrorDetails>\n</ServiceResponse>'

我知道 httplib 和 urllib2 仅当 SSL 被编译到套接字中时才可能工作,其中 SSL 被编译到套接字的模块中。事实上,我已经成功地将 urllib2 用于不同 API 上的其他调用。该问题仅限于此特定 API。

urllib2(和httplib)与curl有什么不同?

注意:所有示例中使用的用户名和密码均相同。

更新:

问题出在基本身份验证密码管理器上。当我手动添加基本授权 header 时,urllib2 cal 可以工作:

>>> import base64
>>> base64string = base64.encodestring('%s:%s' % (username, password))[:-1]
>>> req.add_header("Authorization", "Basic %s" % base64string)
>>> # Make request to fetch url.
... result = urllib2.urlopen(req)
>>> # Read xml results.
... xml = result.read()
>>> xml
'<?xml version="1.0" encoding="UTF-8"?>\n<ServiceResponse xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://qualysapi.qualys.com/qps/xsd/3.0/was/webapp.xsd">\n  <responseCode>SUCCESS</responseCode>\n  <count>33</count>\n</ServiceResponse>'

最佳答案

来自Python urllib2 Basic Auth Problem

The problem [is] that the Python libraries, per HTTP-Standard, first send an unauthenticated request, and then only if it's answered with a 401 retry, are the correct credentials sent. If the ... servers don't do "totally standard authentication" then the libraries won't work.

此特定 API 不会在第一次尝试时以 401 Unauthorized 进行响应,而是以 XML 响应进行响应,其中包含未使用 200 OK 响应代码发送凭据的消息。

关于python - urllib2 HTTPPasswordMgr 不起作用 - 凭据未发送错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9495279/

相关文章:

python - 模式匹配检查大于符号前面是否没有小于符号

python - 如何根据pandas中的字典映射包含多个字符串的列

json - Bash 脚本 : Use string variable in curl JSON Post data

python - 是否有一个 python http-client 可以自动执行多种身份验证类型的身份验证?

Python 2.7 - 重定向处理程序不在重定向时传递参数

python - 使用 lambda 表达式的递归函数

Python 通过写入 stdin 取消 raw_input/input?

android - 如何在 CouchDB 中创建一个数据库,指示用户名和密码

php - curl 错误 60 : SSL certificate in Laravel 5. 4

python - 是否有适用于 Python 2.2 的带有 HTTPCookieProcessor 函数的 urllib2 模块?