以下 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/