urllib2是否支持同时返回基本和摘要认证的服务器
我正在使用urllib2这个库。
我遇到了一个问题,就是在登录一个服务器时,这个服务器同时支持基本认证和摘要认证。
服务器返回的信息是:
WWW-Authenticate: Digest realm="rets@aus.rets.interealty.com",nonce="c068c3d7d30cc0cd80db4d1c599e6d54",opaque="e75078c8-a825-474b-b101-f8ca2d1627ca",qop="auth" WWW-Authenticate: Basic realm="rets@aus.rets.interealty.com"
这是我的代码:
passman = urllib2.HTTPPasswordMgrWithDefaultRealm()
passman.add_password(realm=None, uri='http://aus.rets.interealty.com', user='user', passwd='pwd')
opener = urllib2.build_opener(urllib2.HTTPDigestAuthHandler(passman))
urllib2.install_opener(opener)
retsRequest= urllib2.Request('http://aus.rets.interealty.com/Login.asmx/Login')
retsRequest.add_header("User-Agent", 'userAgent')
retsRequest.add_header("RETS-Version",'retsVersion')
response=urllib2.urlopen(retsRequest)
print response.read()
我可以通过IE浏览器登录这个服务器,看来IE是使用了摘要认证。
2 个回答
0
最近我有时间来看看这个问题,我觉得我找到了答案。这其实是Python的urllib2库里的一个小bug。在urllib2中:
class AbstractDigestAuthHandler:
def http_error_auth_reqed(self, auth_header, host, req, headers):
authreq = headers.get(auth_header, None)
if self.retried > 5:
# Don't fail endlessly - if we failed once, we'll probably
# fail a second time. Hm. Unless the Password Manager is
# prompting for the information. Crap. This isn't great
# but it's better than the current 'repeat until recursion
# depth exceeded' approach <wink>
raise HTTPError(req.get_full_url(), 401, "digest auth failed",
headers, None)
else:
self.retried += 1
if authreq:
scheme = authreq.split()[0]
if scheme.lower() == 'digest':
return self.retry_http_digest_auth(req, authreq)
这里的authreq是:
Basic realm="rets@tra.rets.interealty.com", Digest realm="rets@tra.rets.interealty.com",nonce="512f616ed13813817feddb4fb0ce9e2d",opaque="84f5e814-d38a-44b4-8239-3f5be6ee3153",qop="auth"
authreq.split()[0]的结果会是"Basic",它永远不会是"digest",所以urllib2在进行摘要认证时不会发出第二个请求。
简单来说,urllib2认为在第一次401响应头中只能有一种认证方式。不幸的是,这个服务器返回了两种认证方式。
要解决这个问题,你可以选择使用基本认证,或者使用其他库,比如'requests'。
0
我没有遇到过同样的问题,但曾经惊讶地发现,使用 urllib2.HTTPBasicAuthHandler
的开头实际上会发出两个请求,而不是一个:第一个请求是不带身份验证的,然后如果失败了,第二个请求才会带上身份验证。
这意味着你的情况可能需要三个请求,而第三个请求可能会忘记第二个请求的身份验证信息——最好检查一下。
你可能还需要同时添加 urllib2.HTTPDigestAuthHandler
和 urllib2.HTTPBasicAuthHandler
到开头中。