12 votes

Requêtes Python : Requête POST laissant tomber l'en-tête d'autorisation

J'essaie de faire une demande POST d'API en utilisant la bibliothèque Python requests. Je passe par un Authorization mais lorsque j'essaie de déboguer, je peux voir que l'en-tête est abandonné. Je n'ai aucune idée de ce qui se passe.

Voici mon code :

access_token = get_access_token()
bearer_token = base64.b64encode(bytes("'Bearer {}'".format(access_token)), 'utf-8')
headers = {'Content-Type': 'application/json', 'Authorization': bearer_token}
data = '{"FirstName" : "Jane", "LastName" : "Smith"}'
response = requests.post('https://myserver.com/endpoint', headers=headers, data=data)

Comme vous pouvez le voir ci-dessus, j'ai réglé manuellement le paramètre Authorization dans les arguments de la demande, mais il manque les en-têtes de la demande réelle : {'Connection': 'keep-alive', 'Content-Type': 'application/json', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'User-Agent': 'python-requests/2.4.3 CPython/2.7.9 Linux/4.1.19-v7+'} .

Un élément d'information supplémentaire est que si je change la requête POST en requête GET, l'indicateur Authorization L'en-tête passe normalement !

Pourquoi cette bibliothèque laisse-t-elle tomber l'en-tête pour les requêtes POST et comment faire pour que cela fonctionne ?

Utilisation de la version 2.4.3 de la librairie requests et de Python 2.7.9

21voto

Ni. Points 1792

TLDR

L'url que vous demandez redirige les requêtes POST vers un hôte différent, de sorte que la bibliothèque de requêtes supprime la balise Authoriztion tête de peur que vos informations d'identification ne soient divulguées. Pour résoudre ce problème, vous pouvez remplacer la méthode responsable dans les requêtes Session classe.

Détails

Dans les demandes 2.4.3, le seul endroit où les reqeuests supprime le Authorization est lorsqu'une demande est redirigée vers un autre hôte. Voici le code correspondant :

if 'Authorization' in headers:
    # If we get redirected to a new host, we should strip out any
    # authentication headers.
    original_parsed = urlparse(response.request.url)
    redirect_parsed = urlparse(url)

    if (original_parsed.hostname != redirect_parsed.hostname):
        del headers['Authorization']

Dans les versions plus récentes de requests le Authorization sera supprimé dans d'autres cas (par exemple si la redirection se fait d'un protocole sécurisé vers un protocole non sécurisé).

Ce qui se passe probablement dans votre cas, c'est que vos requêtes POST sont redirigées vers un hôte différent. La seule façon de fournir une authentification pour un hôte redirigé à l'aide de la bibliothèque de requêtes est d'utiliser un fichier de type .netrc fichier. Malheureusement, cela ne vous permettra que d'utiliser HTTP Basic Auth, ce qui ne vous aide pas beaucoup. Dans ce cas, la meilleure solution est probablement de sous-classer requests.Session et remplacer ce comportement, comme ceci :

from requests import Session

class NoRebuildAuthSession(Session):
    def rebuild_auth(self, prepared_request, response):
        """
        No code here means requests will always preserve the Authorization
        header when redirected.
        Be careful not to leak your credentials to untrusted hosts!
        """

session = NoRebuildAuthSession()
response = session.post('https://myserver.com/endpoint', headers=headers, data=data)

Modifier

J'ai ouvert un demande de tirage au sort à la bibliothèque requests sur github pour ajouter un avertissement lorsque cela se produit. Il est en attente d'une deuxième approbation pour être fusionné (trois mois déjà).

2voto

Tarique Points 895

C'est ce que dit la documentation de la demande :

Authorization headers set with headers= will be overridden if credentials are specified in .netrc, which in turn will be overridden by the auth= parameter. Authorization headers will be removed if you get redirected off-host.

Êtes-vous redirigé dans votre demande ?

Si c'est le cas, essayez de désactiver la redirection avec cette option dans la requête post :

allow_redirects=False

0voto

Odysseus Points 830

Le premier (et peut-être le principal) problème que je vois est la manière dont vous créez bearer_token parce que vous n'encodez pas seulement votre jeton mais aussi le type d'authentification 'Bearer'

Si j'ai bien compris, il suffit de coder le jeton et de fournir le type d'authentification vide + le jeton codé dans l'en-tête de la requête :

bearer_token = str(base64.b64encode(access_token.encode()), "utf8")
headers = {'Content-Type': 'application/json', 'Authorization': 'Bearer {}'.format(bearer_token)}

S'il s'agit (également) d'un problème de redirection, vous pouvez simplement trouver l'emplacement correct et faire votre demande à cette url ou vous pouvez envisager d'envoyer le jeton d'accès dans le corps de votre demande. POST si le serveur l'accepte.

0voto

yoshikage_kira Points 21

Dans la documentation : Requests will attempt to get the authentication credentials for the URL’s hostname from the user’s netrc file. The netrc file overrides raw HTTP authentication headers set with headers=. If credentials for the hostname are found, the request is sent with HTTP Basic Auth.

Si vous êtes redirigé, vous pouvez essayer d'utiliser allow_redirects=false

-1voto

Tarique Points 895

Vous pouvez essayer d'utiliser une autorisation personnalisée dans les en-têtes.

Définir une classe d'authentification personnalisée :

class MyAuth(requests.auth.AuthBase):
def __init__(self, bearer_token):
    self.username = None
    self.bearer_token = bearer_token

def __call__(self, r):
    r.headers['Authorization'] = self.bearer_token
    return r

puis l'utiliser pour envoyer la demande :

headers = {'Content-Type': 'application/json'}

data = '{"FirstName" : "Jane", "LastName" : "Smith"}'

response = requests.post('https://myserver.com/endpoint', headers=headers, auth=MyAuth(bearer_token), data=data)

Si cela fonctionne, veuillez accepter la réponse. Ou si vous avez encore des problèmes, faites-le nous savoir. J'espère que cela vous aidera.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X