This module contains the authentication handlers for Requests. """
import hashlib import os import re import threading import time import warnings from base64 import b64encode
from ._internal_utils import to_native_string from .compat import basestring, str, urlparse from .cookies import extract_cookies_to_jar from .utils import parse_dict_header
def _basic_auth_str(username, password): """Returns a Basic Auth string."""
# "I want us to put a big-ol' comment on top of it that # says that this behaviour is dumb but we need to preserve # it because people are relying on it." # - Lukasa # # These are here solely to maintain backwards compatibility # for things like ints. This will be removed in 3.0.0. ifnot isinstance(username, basestring):
warnings.warn( "Non-string usernames will no longer be supported in Requests " "3.0.0. Please convert the object you've passed in ({!r}) to " "a string or bytes object in the near future to avoid " "problems.".format(username),
category=DeprecationWarning,
)
username = str(username)
ifnot isinstance(password, basestring):
warnings.warn( "Non-string passwords will no longer be supported in Requests " "3.0.0. Please convert the object you've passed in ({!r}) to " "a string or bytes object in the near future to avoid " "problems.".format(type(password)),
category=DeprecationWarning,
)
password = str(password) # -- End Removal --
if isinstance(username, str):
username = username.encode("latin1")
if isinstance(password, str):
password = password.encode("latin1")
if algorithm isNone:
_algorithm = "MD5" else:
_algorithm = algorithm.upper() # lambdas assume digest modules are imported at the top level if _algorithm == "MD5"or _algorithm == "MD5-SESS":
def md5_utf8(x): if isinstance(x, str):
x = x.encode("utf-8") return hashlib.md5(x).hexdigest()
hash_utf8 = md5_utf8 elif _algorithm == "SHA":
def sha_utf8(x): if isinstance(x, str):
x = x.encode("utf-8") return hashlib.sha1(x).hexdigest()
# XXX not implemented yet
entdig = None
p_parsed = urlparse(url) #: path is request-uri defined in RFC 2616 which should not be empty
path = p_parsed.path or"/" if p_parsed.query:
path += f"?{p_parsed.query}"
# XXX should the partial digests be encoded too?
base = (
f'username="{self.username}", realm="{realm}", nonce="{nonce}", '
f'uri="{path}", response="{respdig}"'
) if opaque:
base += f', opaque="{opaque}"' if algorithm:
base += f', algorithm="{algorithm}"' if entdig:
base += f', digest="{entdig}"' if qop:
base += f', qop="auth", nc={ncvalue}, cnonce="{cnonce}"'
return f"Digest {base}"
def handle_redirect(self, r, **kwargs): """Reset num_401_calls counter on redirects.""" if r.is_redirect:
self._thread_local.num_401_calls = 1
def handle_401(self, r, **kwargs): """
Takes the given response and tries digest-auth, if needed.
if self._thread_local.pos isnotNone: # Rewind the file position indicator of the body to where # it was to resend the request.
r.request.body.seek(self._thread_local.pos)
s_auth = r.headers.get("www-authenticate", "")
if"digest"in s_auth.lower() and self._thread_local.num_401_calls < 2:
# Consume content and release the original connection # to allow our new request to reuse the same one.
r.content
r.close()
prep = r.request.copy()
extract_cookies_to_jar(prep._cookies, r.request, r.raw)
prep.prepare_cookies(prep._cookies)
def __call__(self, r): # Initialize per-thread state, if needed
self.init_per_thread_state() # If we have a saved nonce, skip the 401 if self._thread_local.last_nonce:
r.headers["Authorization"] = self.build_digest_header(r.method, r.url) try:
self._thread_local.pos = r.body.tell() except AttributeError: # In the case of HTTPDigestAuth being reused and the body of # the previous request was a file-like object, pos has the # file position of the previous body. Ensure it's set to # None.
self._thread_local.pos = None
r.register_hook("response", self.handle_401)
r.register_hook("response", self.handle_redirect)
self._thread_local.num_401_calls = 1
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.