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

Python urllib2是否支持同时返回基本和摘要身份验证的服务器,python,urllib2,http-authentication,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.i

我正在使用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"
我可以使用IE登录此服务器,IE似乎使用摘要身份验证。

我没有遇到同样的问题,但是,有一次我惊讶地发现,带有
urllib2.HTTPBasicAuthHandler
的开场白实际上发出了两个请求,而不是一个请求:第一个没有身份验证,然后作为回退,第二个有身份验证

也就是说,您的案例可能需要三个请求,其中第三个请求可能会忘记第二个请求的身份验证—一个应该检查


您可能应该在开场白中同时添加:
urlib2.HTTPDigestAuthHandler
urlib2.HTTPBasicAuthHandler

最近我有时间回顾这个问题,我想我找到了答案。这是python urlib2的一个缺陷。在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.split()[0]将是“基本的”,它永远不会是“摘要的”,因此urllib2不会在摘要身份验证中执行第二个请求

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


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

我尝试添加urlib2.HTTPDigestAuthHandler和urlib2.HTTPBasicAuthHandler,但都不起作用。我只需添加一个头即可登录此服务器:base64string=base64.encodestring(“%s:%s%”(retsUSER,retsPWD))[:-1]retsRequest.add_头(“授权”,“基本%s”%base64string),因此我决定选择这种方式。
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)
Basic realm="rets@tra.rets.interealty.com", Digest realm="rets@tra.rets.interealty.com",nonce="512f616ed13813817feddb4fb0ce9e2d",opaque="84f5e814-d38a-44b4-8239-3f5be6ee3153",qop="auth"