urllib2支持主动认证吗?

2 投票
3 回答
3180 浏览
提问于 2025-04-16 09:35

我正在尝试访问一个REST API。

我可以在Curl/REST Client(一个用户界面工具)中让它正常工作,并且启用了预先认证。

但是,使用urllib2时,它似乎默认不支持这个功能,我找不到开启它的方法。

谢谢 :)

3 个回答

0

根据你需要的认证方式,你可以手动添加授权头信息,把它们放到请求里,然后再发送请求的内容。

4

这段话的意思是,和@thom-nichols的回答类似,但这里是通过创建一个新的类来扩展HTTPBasicAuthHandler,同时也能处理HTTPS请求。

import urllib2
import base64

class PreemptiveBasicAuthHandler(urllib2.HTTPBasicAuthHandler):
    '''Preemptive basic auth.

    Instead of waiting for a 403 to then retry with the credentials,
    send the credentials if the url is handled by the password manager.
    Note: please use realm=None when calling add_password.'''
    def http_request(self, req):
        url = req.get_full_url()
        realm = None
        # this is very similar to the code from retry_http_basic_auth()
        # but returns a request object.
        user, pw = self.passwd.find_user_password(realm, url)
        if pw:
            raw = "%s:%s" % (user, pw)
            auth = 'Basic %s' % base64.b64encode(raw).strip()
            req.add_unredirected_header(self.auth_header, auth)
        return req

    https_request = http_request

接下来是一个处理Jenkins服务器的例子,这个服务器不会给你发送401的HTTP错误(也就是不会提示你需要重新认证)。我使用urllib2.install_opener来简化操作。

jenkins_url = "https://jenkins.example.com"
username = "johndoe"
api_token = "some-cryptic-value"

auth_handler = PreemptiveBasicAuthHandler()
auth_handler.add_password(
    realm=None, # default realm.
    uri=jenkins_url,
    user=username,
    passwd=api_token)
opener = urllib2.build_opener(auth_handler)
urllib2.install_opener(opener)
6

这里有一个简单的预先认证的HTTP基本认证处理器,它是基于urllib2.HTTPBasicAuthHandler的代码。你可以用它的方式和之前一样,只不过它会在每个匹配的URL请求中添加一个Authorization头。需要注意的是,这个处理器应该和HTTPPasswordMgrWithDefaultRealm一起使用。原因是因为在你进行预先认证时,WWW-Authenticate挑战中不会返回任何领域信息。

class PreemptiveBasicAuthHandler(urllib2.BaseHandler):

        def __init__(self, password_mgr=None):
                if password_mgr is None:
                        password_mgr = urllib2.HTTPPasswordMgrWithDefaultRealm()
                self.passwd = password_mgr
                self.add_password = self.passwd.add_password

        def http_request(self,req):
                uri = req.get_full_url()
                user, pw = self.passwd.find_user_password(None,uri)
                #logging.debug('ADDING REQUEST HEADER for uri (%s): %s:%s',uri,user,pw)
                if pw is None: return req

                raw = "%s:%s" % (user, pw)
                auth = 'Basic %s' % base64.b64encode(raw).strip()
                req.add_unredirected_header('Authorization', auth)
                return req

撰写回答