Fazer uma chamada de API em Python com uma API que requer um token de portador


98

Procurando alguma ajuda com a integração de uma chamada de API JSON em um programa Python.

Estou procurando integrar a seguinte API em um programa Python .py para permitir que ela seja chamada e a resposta seja impressa.

A orientação da API afirma que um token do portador deve ser gerado para permitir chamadas para a API, o que eu fiz com sucesso. No entanto, não tenho certeza da sintaxe para incluir esse token como autenticação de token do portador na solicitação da API Python.

Posso concluir com êxito a solicitação acima usando cURL com um token incluído. Eu tentei as rotas "urllib" e "solicitações", mas sem sucesso.

Detalhes completos da API: IBM X-Force Exchange API Documentation - IP Reputation

Respostas:


147

Significa apenas que espera que, como uma chave nos dados do seu cabeçalho

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

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

O 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 código acima lança o seguinte erro de sintaxe: Código abaixo: 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() alguma ideia?
user4657

você tem uma versão antiga de solicitações ... jsoné um dicionário em sua versão e não uma função requests.post(...).json ... não chame
Joran Beasley

Obrigado Joran Beasley. Biblioteca de solicitações atualizada via pip e isso me permitiu manter a sintaxe original. No entanto, agora, quando eu executo o acima, ele produz esta resposta .json: {u'error': u'Not authorized. Access is only allowed via https://exchange.xforce.ibmcloud.com/#/'} Isso é o mesmo que se eu acessasse a URL diretamente em um navegador. Estou perdendo algo com o token ou o ponto de extremidade do caminho está configurado? Código: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

infelizmente não posso ajudar com isso ... ou é um endpoint ruim ou suas credenciais são inválidas (você está usando o token de exemplo deles, que está configurado apenas para o url deles?) ou talvez você precise colocar o url do aplicativo em seu delegado painel para o seu código ... é provável que este seja o seu primeiro token ... você precisa trocar o token por um token de atualização que você pode usar para obter um token mais permanente (pelo menos é assim que oauth2 geralmente funciona ...)
Joran Beasley

Ops, parece que o cabeçalho está errado, tente o código atualizado
Joran Beasley

56

Se você estiver usando o requestsmódulo, uma opção alternativa é escrever uma classe de autenticação, conforme discutido em " Novas formas de autenticação ":

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 então você pode enviar pedidos como este

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

que permite que você use o mesmo auth argumento como o auth básico e pode ajudá-lo em certas situações.


Isso também pode ser útil com o zeep. Ele usa o tipo de autorização requests.auth (para autenticação de cabeçalhos http, não cabeçalhos de sabão)
smido

20

O token deve ser colocado em um cabeçalho de autorização de acordo com o seguinte formato:

Autorização: Portador [Token_Value]

Código abaixo:

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

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

0

Aqui está um exemplo completo de implementação em cURL e em Python - para autorização e para fazer chamadas de API

ondulação

1. Autorização

Você recebeu dados de acesso como estes:

Username: johndoe

Password: zznAQOoWyj8uuAgq

Consumer Key: ggczWttBWlTjXCEtk3Yie_WJGEIa

Consumer Secret: uuzPjjJykiuuLfHkfgSdXLV98Ciga

Que você pode chamar em cURL assim:

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

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

                       https://somedomain.test.com/token

ou para este caso seria:

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

                    -H "Authorization: Basic zzRjettzNUJXbFRqWENuuGszWWllX1iiR0VJYTpRelBLZkp5a2l2V0xmSGtmZ1NkWExWzzhDaWdh" \

                      https://somedomain.test.com/token

A resposta seria algo como:

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

2. API de chamada

Aqui está como você chama alguma API que usa autenticação de cima. Limite offsetsão apenas exemplos de 2 parâmetros que a API pode implementar. Você precisa access_tokende acima inserido após "Bearer ". Então, aqui está como você chama algumas API com dados de autenticação acima:

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"

Pitão

A mesma coisa acima implementada em Python. Coloquei texto nos comentários para que o código pudesse ser copiado e colado.

# 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 Seu comentário não tem nada a ver com a questão do OP. Minha resposta funciona perfeitamente para o caso dele.
Harvey
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.