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.