Richieste Python: richiesta POST che elimina l'intestazione di autorizzazione


9

Sto provando a fare una richiesta POST API utilizzando la libreria di richieste Python. Sto passando Authorizationun'intestazione ma quando provo a eseguire il debug, vedo che l'intestazione viene rilasciata. Non ho idea di cosa stia succedendo.

Ecco il mio codice:

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)

Come potete vedere sopra, ho impostato manualmente l' Authorizationintestazione negli argomenti di richiesta, ma manca le intestazioni della richiesta effettiva: {'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'ulteriore informazione è che se cambio la richiesta POST in una richiesta GET, l' Authorizationintestazione passa normalmente!

Perché questa libreria dovrebbe eliminare l'intestazione per le richieste POST e come posso farlo funzionare?

Uso della v2.4.3 delle richieste lib e Python 2.7.9

Risposte:


9

TLDR

L'URL che stai richiedendo reindirizza le richieste POST a un host diverso, quindi la libreria delle richieste rilascia l' Authoriztionintestazione nel timore di perdere le tue credenziali. Per risolvere il problema, è possibile ignorare il metodo responsabile nella Sessionclasse delle richieste .

Dettagli

Nelle richieste 2.4.3, l'unico posto in cui viene reqeuestsrimossa l' Authorizationintestazione è quando una richiesta viene reindirizzata a un host diverso. Questo è il codice pertinente :

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']

Nelle versioni più recenti di requests, l' Authorizationintestazione verrà eliminata in casi aggiuntivi (ad esempio se il reindirizzamento è da un protocollo sicuro a un protocollo non sicuro).

Quindi, ciò che probabilmente accade nel tuo caso, è che le tue richieste POST vengano reindirizzate a un host diverso. L'unico modo in cui è possibile fornire l'autenticazione per un host reindirizzato utilizzando la libreria delle richieste è tramite un .netrcfile. Purtroppo, ciò ti consentirà solo di utilizzare HTTP Basic Auth, il che non ti aiuta molto. In tal caso, la soluzione migliore è probabilmente la sottoclasse requests.Sessione l'override di questo comportamento, in questo modo:

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)

1
Grazie, questo era il problema!
— user4184113

0

Questo è ciò che dice la documentazione richiesta:

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.

Verrai reindirizzato nella tua richiesta?

In questo caso prova a disabilitare il reindirizzamento con questa opzione in post-richiesta:

allow_redirects=False


allow_redirects=Falseimpedirà alle richieste di seguire il reindirizzamento richiesto dal server. Questo non aiuterà a completare la richiesta, ma la fermerà nel mezzo.
— kmaork,

0

Il primo (e forse l'effettivo) problema che vedo è come si crea bearer_tokenperché non si codifica solo il token ma anche il tipo di autenticazione'Bearer'

Come ho capito, devi solo codificare il token e devi fornire il tipo di autenticazione vuoto + il token codificato all'interno dell'intestazione della richiesta:

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

Se si tratta (anche) di un problema di reindirizzamento, potresti semplicemente scoprire la posizione corretta ed effettuare la tua richiesta a questo url o potresti pensare di inviare il token di accesso all'interno del tuo corpo POSTse il server lo accetta.


0

Dalla documentazione: 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.

Se vieni reindirizzato, puoi provare a utilizzare allow_redirects=false


-1

puoi provare a utilizzare un'autorizzazione personalizzata nelle intestazioni.

Definire una classe di autenticazione personalizzata:

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

quindi utilizzalo per inviare la richiesta:

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)

Se funziona, accetta la risposta. O se hai ancora problemi, faccelo sapere. Spero che sia di aiuto.


Non è necessario ereditare da requests.auth.AuthBase. Se guardi il codice sorgente, vedrai che tutto ciò che fa è aumentare NotImplementedse dimentichi di scavalcare __call__.
— Ripristina Monica il

Ciò non cambierà il comportamento descritto nella domanda. Quando si ricostruisce l'autent su un reindirizzamento, le richieste non utilizzano l'argomento auth.
— kmaork,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.