urllib2是否支持同时返回基本身份验证和摘要身份验证的服务器

时间:2012-01-15 14:32:05

标签: python urllib2 http-authentication

我正在使用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 :(得分:0)

我没有遇到同样的问题,但曾经惊讶地发现urllib2.HTTPBasicAuthHandler的开启者实际上只有两个请求而不是一个请求:第一个没有身份验证,然后是第二个带有身份验证的后退。

这可能会导致您的案件需要三个请求,其中第三个请求可能会忘记第二个请求的验证 - 应该检查。

你应该将两者:urllib2.HTTPDigestAuthHandlerurllib2.HTTPBasicAuthHandler添加到开场白。

答案 1 :(得分: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]将是“基本”,它永远不会是“摘要”,因此urllib2将不会在摘要认证中执行第二个请求。

基本上,urllib2假设只有一个身份验证可以在第一个401响应头中。不幸的是,这个服务器返回两种类型的身份验证。

要解决此问题,您可以使用基本身份验证,也可以使用“请求”等其他库。