mirror of
https://github.com/python/cpython.git
synced 2025-11-19 02:39:15 +00:00
Close #19494: add urrlib.request.HTTPBasicPriorAuthHandler
This auth handler adds the Authorization header to the first HTTP request rather than waiting for a HTTP 401 Unauthorized response from the server as the default HTTPBasicAuthHandler does. This allows working with websites like https://api.github.com which do not follow the strict interpretation of RFC, but more the dicta in the end of section 2 of RFC 2617: > A client MAY preemptively send the corresponding Authorization > header with requests for resources in that space without receipt > of another challenge from the server. Similarly, when a client > sends a request to a proxy, it may reuse a userid and password in > the Proxy-Authorization header field without receiving another > challenge from the proxy server. See section 4 for security > considerations associated with Basic authentication. Patch by Matej Cepl.
This commit is contained in:
parent
ab14088141
commit
c216c48699
5 changed files with 53 additions and 0 deletions
|
|
@ -1422,6 +1422,21 @@ class HandlerTests(unittest.TestCase):
|
|||
handler.do_open(conn, req)
|
||||
self.assertTrue(conn.fakesock.closed, "Connection not closed")
|
||||
|
||||
def test_auth_prior_handler(self):
|
||||
pwd_manager = MockPasswordManager()
|
||||
pwd_manager.add_password(None, 'https://example.com',
|
||||
'somebody', 'verysecret')
|
||||
auth_prior_handler = urllib.request.HTTPBasicPriorAuthHandler(
|
||||
pwd_manager)
|
||||
http_hand = MockHTTPSHandler()
|
||||
|
||||
opener = OpenerDirector()
|
||||
opener.add_handler(http_hand)
|
||||
opener.add_handler(auth_prior_handler)
|
||||
|
||||
req = Request("https://example.com")
|
||||
opener.open(req)
|
||||
self.assertNotIn('Authorization', http_hand.httpconn.req_headers)
|
||||
|
||||
class MiscTests(unittest.TestCase):
|
||||
|
||||
|
|
|
|||
|
|
@ -916,6 +916,21 @@ class ProxyBasicAuthHandler(AbstractBasicAuthHandler, BaseHandler):
|
|||
return response
|
||||
|
||||
|
||||
class HTTPBasicPriorAuthHandler(HTTPBasicAuthHandler):
|
||||
handler_order = 400
|
||||
|
||||
def http_request(self, req):
|
||||
if not req.has_header('Authorization'):
|
||||
user, passwd = self.passwd.find_user_password(None, req.host)
|
||||
credentials = '{0}:{1}'.format(user, passwd).encode()
|
||||
auth_str = base64.standard_b64encode(credentials).decode()
|
||||
req.add_unredirected_header('Authorization',
|
||||
'Basic {}'.format(auth_str.strip()))
|
||||
return req
|
||||
|
||||
https_request = http_request
|
||||
|
||||
|
||||
# Return n random bytes.
|
||||
_randombytes = os.urandom
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue