使用需要Bearer Token的API在Python中进行API调用

219

正在寻求帮助,将一个JSON API调用集成到Python程序中。

我想将以下API集成到Python .py程序中,以便可以调用它并打印响应。

API指南说明必须生成一个bearer令牌才能允许调用API,我已经成功完成了这项工作。但是,我不确定如何在Python API请求中包含此令牌作为bearer令牌身份验证的语法。

我可以使用包含令牌的cURL成功完成上述请求。我尝试过“urllib”和“requests”路径,但都没有成功。

完整的API详细信息:IBM X-Force Exchange API Documentation - IP Reputation

5个回答

320

这只是意味着它期望在您的标头数据中作为一个键。

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

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

以上代码会抛出以下语法错误: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下面是代码:`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()`有什么想法吗? - user4657
你的requests版本过旧了... 在你的版本中,json是一个字典而不是函数requests.post(...).json ... 不要这样调用 - Joran Beasley
感谢Joran Beasley。通过pip更新了Requests库,这使我能够保留原始语法。但是现在当我运行上面的代码时,它输出以下.json响应:{u'error': u'Not authorized. Access is only allowed via https://exchange.xforce.ibmcloud.com/#/'}这与我在浏览器中直接访问URL的情况相同。我是否遗漏了令牌或端点配置的方式?代码: 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
糟糕,看起来我的头文件有误,请尝试更新后的代码。 - Joran Beasley
尝试更新代码:更成功了。但仍然抛出以下错误。{u'error': u'Not found.'}代码:`import requests endpoint = "https://xforce-api.mybluemix.net:443/ipr/" data = {"ip":"8.8.8.8"} headers = {"Authorization":"Bearer REALLY_LONG_TOKEN_HERE"}print requests.post(endpoint,data=data,headers=headers).json()`API文档在这里:https://xforce-api.mybluemix.net/doc/#!/Authentication/auth_anonymousToken_get非常感谢您迄今为止的帮助!Joran,真的非常感激。 - user4657
显示剩余3条评论

169
如果您正在使用requests模块,另一种选择是编写一个auth类,如“新的认证形式”中所讨论的那样:
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

然后你可以像这样发送请求

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

这允许您像基本身份验证一样使用相同的auth参数,并在某些情况下对您有所帮助。


这对于使用zeep也可能很有用。它使用requests.auth类型的授权(用于http头身份验证,而不是soap头)。 - smido

25

根据以下格式,令牌必须放置在Authorization头中:

Authorization: Bearer [Token_Value]

以下是代码:

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

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

25

以下是使用cURL和Python进行授权和调用API的完整示例

cURL

1. 授权

您已收到类似以下的访问数据:

Username: johndoe

Password: zznAQOoWyj8uuAgq

Consumer Key: ggczWttBWlTjXCEtk3Yie_WJGEIa

Consumer Secret: uuzPjjJykiuuLfHkfgSdXLV98Ciga

你可以用curl这样调用:

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

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

                       https://somedomain.test.com/token

或者对于这种情况,它将是:

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

                    -H "Authorization: Basic zzRjettzNUJXbFRqWENuuGszWWllX1iiR0VJYTpRelBLZkp5a2l2V0xmSGtmZ1NkWExWzzhDaWdh" \

                      https://somedomain.test.com/token

答案应该如下:

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

2. 调用 API

下面是如何调用使用上述认证的某些 API。 Limitoffset 只是 API 可能实现的 2 个参数示例。 你需要在 "Bearer " 后插入上述获取的 access_token。因此,以下是如何使用上述认证数据调用某些 API 的方法:

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"

Python

以下为使用Python实现与上述代码相同的功能。我将文本放在注释中,以便可以复制粘贴代码。

# 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()

1
这个可以工作。但是我遇到了一个奇怪的问题。第一次“请求”调用总是返回“401”,而第二次调用(使用相同的数据)却可以正常工作!有没有办法避免第二次调用?目前,我正在检查第一次调用的“status_code”,如果是“401”,我就会进行第二次调用。 - Sarang
关于这个回答的第一行:你不必大声喊叫来引起点赞的注意(-1)。 - Luc

4
import json
import os
import requests

def lambda_handler(event, context):
    print(event)
    item = list(map(lambda x: x['detail']['item'], event['inputData']))
    print("item List :", item)
    consumer_key = os.getenv('consumer_key')
    consumer_secret = os.getenv('consumer_secret')
    entitlement_url=os.getenv('entitlement_url')
    storage_url=os.getenv('storage_url')
    access_token = get_jwt_token(consumer_key,consumer_secret,entitlement_url)
    print("Response from entitlement: ", access_token)
    for listID in list:
        print("listID: ", listID)
        response = get_storage_service(access_token,storage_url,listID)
        print("Response from storage: ", response.text)

    return "Success"

def get_jwt_token(consumer_key, consumer_secret, url):
    data = 'grant_type=client_credentials&client_id=' + consumer_key + '&client_secret=' + consumer_secret
    header = {"Content-type": "application/x-www-form-urlencoded"}
    try:
        response = requests.post(url, data=data, headers=header)
        access_token = json.loads(response.text)
        final_response=access_token['access_token']

    except requests.exceptions as err:
        print(err)
        final_response = 'error'
    return final_response


def get_storage_service(jwt_token, url, list_id):
    final_url = url + list_id + "/data"
    print("Final url is :", final_url)
    headers_api = {
        'Authorization': 'Bearer ' + jwt_token

    }
    try:
        response = requests.get(url=final_url, headers=headers_api)
    except requests.exceptions as err:
        print(err)
        response = 'error'
    return response

使用环境变量


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接