Effettuare una chiamata API in Python con un'API che richiede un token portatore


98

Alla ricerca di aiuto per l'integrazione di una chiamata API JSON in un programma Python.

Sto cercando di integrare la seguente API in un programma Python .py per consentirne il richiamo e la stampa della risposta.

La guida API afferma che un token di trasporto deve essere generato per consentire le chiamate all'API, operazione che ho eseguito correttamente. Tuttavia, non sono sicuro della sintassi per includere questo token come autenticazione del token portatore nella richiesta API Python.

Posso completare con successo la richiesta di cui sopra utilizzando cURL con un token incluso. Ho provato le rotte "urllib" e "richieste" ma senza successo.

Dettagli API completi: Documentazione API IBM X-Force Exchange - Reputazione IP

Risposte:


147

Significa solo che se lo aspetta come chiave nei dati dell'intestazione

import requests
endpoint = ".../api/ip"
data = {"ip": "1.1.2.3"}
headers = {"Authorization": "Bearer MYREALLYLONGTOKENIGOT"}

print(requests.post(endpoint, data=data, headers=headers).json())

Quanto sopra genera il seguente errore di sintassi: Traceback (most recent call last): File "bearerreturn.py", line 6, in <module> print requests.post(endpoint,data=data,headers=headers).json() TypeError: 'dict' object is not callable Code Below: import requests endpoint = "https://xforce-api.mybluemix.net:443/api/ip" data = {"ip":"1.1.2.3"} headers = {"Bearer token":"TOKEN WAS INSERTED HERE"} print requests.post(endpoint,data=data,headers=headers).json() Any Ideas?
user4657

hai una vecchia versione di richieste ... jsonè un dict nella tua versione e non una funzione requests.post(...).json ... non chiamarla
Joran Beasley

Grazie Joran Beasley. Libreria Richieste aggiornata tramite pip e questo mi ha permesso di mantenere la sintassi originale. Tuttavia ora, quando eseguo quanto sopra, emette questa risposta .json: {u'error': u'Not authorized. Access is only allowed via https://exchange.xforce.ibmcloud.com/#/'} è come se colpissi l'URL direttamente in un browser. Mi manca qualcosa con il token o il modo in cui è configurato l'endpoint? Codice:import requests endpoint = "https://xforce-api.mybluemix.net:443/ipr/" data = {"ip":"1.1.2.3"} headers = {"Bearer token":"TOKEN_HERE"} print requests.post(endpoint,data=data,headers=headers).json()
user4657

sfortunatamente non posso davvero aiutarti ... o è un endpoint sbagliato o le tue credenziali non sono valide (stai usando il loro token di esempio, che è configurato solo per il loro URL?) O forse devi mettere l'URL della tua app nel loro deleoper pannello per il tuo codice ... è probabile che sia il tuo primo token ... devi scambiare il token con un token di aggiornamento che puoi utilizzare per ottenere un token più permanente (almeno è così che di solito funziona oauth2 ..)
Joran Beasley

Ops sembra che io abbia sbagliato intestazione prova il codice aggiornato
Joran Beasley

56

Se stai usando il requestsmodulo, un'opzione alternativa è scrivere una classe di autenticazione, come discusso in " Nuove forme di autenticazione ":

import requests

class BearerAuth(requests.auth.AuthBase):
    def __init__(self, token):
        self.token = token
    def __call__(self, r):
        r.headers["authorization"] = "Bearer " + self.token
        return r

e poi puoi inviare richieste come questa

response = requests.get('https://www.example.com/', auth=BearerAuth('3pVzwec1Gs1m'))

che ti consente di utilizzare lo stesso authargomento proprio come l'autenticazione di base e può aiutarti in determinate situazioni.


Questo potrebbe essere utile anche con zeep. Utilizza il tipo di autorizzazioni
request.auth

20

Il token deve essere inserito in un'intestazione di autorizzazione secondo il seguente formato:

Autorizzazione: portatore [Token_Value]

Codice di seguito:

import urllib2
import json

def get_auth_token():
    """
    get an auth token
    """
    req=urllib2.Request("https://xforce-api.mybluemix.net/auth/anonymousToken")
    response=urllib2.urlopen(req)
    html=response.read()
    json_obj=json.loads(html)
    token_string=json_obj["token"].encode("ascii","ignore")
    return token_string

def get_response_json_object(url, auth_token):
    """
    returns json object with info
    """
    auth_token=get_auth_token()
    req=urllib2.Request(url, None, {"Authorization": "Bearer %s" %auth_token})
    response=urllib2.urlopen(req)
    html=response.read()
    json_obj=json.loads(html)
    return json_obj

Per Python3:req = urllib.request.Request(urlstr, None, {"Authorization": "Bearer %s" % enc_authstr}) response = urllib.request.urlopen(req)
SidJ

0

Ecco un esempio completo di implementazione in cURL e in Python - per l'autorizzazione e per effettuare chiamate API

arricciare

1. Autorizzazione

Hai ricevuto dati di accesso in questo modo:

Username: johndoe

Password: zznAQOoWyj8uuAgq

Consumer Key: ggczWttBWlTjXCEtk3Yie_WJGEIa

Consumer Secret: uuzPjjJykiuuLfHkfgSdXLV98Ciga

Che puoi chiamare in cURL in questo modo:

curl -k -d "grant_type=password&username=Username&password=Password" \

                    -H "Authorization: Basic Base64(consumer-key:consumer-secret)" \

                       https://somedomain.test.com/token

o per questo caso sarebbe:

curl -k -d "grant_type=password&username=johndoe&password=zznAQOoWyj8uuAgq" \

                    -H "Authorization: Basic zzRjettzNUJXbFRqWENuuGszWWllX1iiR0VJYTpRelBLZkp5a2l2V0xmSGtmZ1NkWExWzzhDaWdh" \

                      https://somedomain.test.com/token

La risposta sarebbe qualcosa del tipo:

{
    "access_token": "zz8d62zz-56zz-34zz-9zzf-azze1b8057f8",
    "refresh_token": "zzazz4c3-zz2e-zz25-zz97-ezz6e219cbf6",
    "scope": "default",
    "token_type": "Bearer",
    "expires_in": 3600
}

2. Chiamata API

Ecco come chiamare alcune API che utilizzano l'autenticazione dall'alto. Limite offsetsono solo esempi di 2 parametri che l'API potrebbe implementare. È necessario access_tokeninserire dall'alto dopo "Bearer ". Quindi ecco come chiamare alcune API con i dati di autenticazione dall'alto:

curl -k -X GET "https://somedomain.test.com/api/Users/Year/2020/Workers?offset=1&limit=100" -H "accept: application/json" -H "Authorization: Bearer zz8d62zz-56zz-34zz-9zzf-azze1b8057f8"

Pitone

Stessa cosa dall'alto implementata in Python. Ho inserito del testo nei commenti in modo che il codice possa essere copiato e incollato.

# Authorization data

import base64
import requests

username = 'johndoe'
password= 'zznAQOoWyj8uuAgq'
consumer_key = 'ggczWttBWlTjXCEtk3Yie_WJGEIa'
consumer_secret = 'uuzPjjJykiuuLfHkfgSdXLV98Ciga'
consumer_key_secret = consumer_key+":"+consumer_secret
consumer_key_secret_enc = base64.b64encode(consumer_key_secret.encode()).decode()

# Your decoded key will be something like:
#zzRjettzNUJXbFRqWENuuGszWWllX1iiR0VJYTpRelBLZkp5a2l2V0xmSGtmZ1NkWExWzzhDaWdh


headersAuth = {
    'Authorization': 'Basic '+ str(consumer_key_secret_enc),
}

data = {
  'grant_type': 'password',
  'username': username,
  'password': password
}

## Authentication request

response = requests.post('https://somedomain.test.com/token', headers=headersAuth, data=data, verify=True)
j = response.json()

# When you print that response you will get dictionary like this:

    {
        "access_token": "zz8d62zz-56zz-34zz-9zzf-azze1b8057f8",
        "refresh_token": "zzazz4c3-zz2e-zz25-zz97-ezz6e219cbf6",
        "scope": "default",
        "token_type": "Bearer",
        "expires_in": 3600
    }

# You have to use `access_token` in API calls explained bellow.
# You can get `access_token` with j['access_token'].


# Using authentication to make API calls   

## Define header for making API calls that will hold authentication data

headersAPI = {
    'accept': 'application/json',
    'Authorization': 'Bearer '+j['access_token'],
}

### Usage of parameters defined in your API
params = (
    ('offset', '0'),
    ('limit', '20'),
)

# Making sample API call with authentication and API parameters data

response = requests.get('https://somedomain.test.com/api/Users/Year/2020/Workers', headers=headersAPI, params=params, verify=True)
api_response = response.json()

@KurtPeters Il tuo commento non ha nulla a che fare con la domanda OP. La mia risposta funziona perfettamente per il suo caso.
Harvey
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.