Python使用用户名,密码和API密钥连接到API

时间:2018-08-12 19:23:25

标签: python api authentication

我已经设置了对网站的API访问权限,并且可以使用其测试GUI界面使用用户名,密码和API密钥进行连接(HTTP 200)。

如果我尝试下面的代码,则会收到错误响应403:

 from requests.auth import HTTPDigestAuth
 url = 'https://website.com'
 result = requests.get(url, auth=HTTPDigestAuth('username', 'password'))

我认为我需要在原始requests.get中包含API密钥,但是我不确定该怎么做。

这是一个REST API。在网站上,我通过提供名称来生成API密钥,然后设置API登录详细信息(用户名和密码)。在HTTP请求的信息下,它列出了请求标头组件:

X-API-KEY:k API密钥k(从“我的帐户”获得)是我们识别和授权调用应用程序的方式

CST /授权(有效),用于标识客户端。

X-SECURITY-TOKEN / ACCOUNT-ID (有效帐户令牌或帐户ID),用于标识客户的当前帐户。

内容类型:application / json 。请求格式类型。应始终按照仅对json的指示进行设置

接受:application / json; charset = UTF-8 响应格式类型。应始终按照仅针对json的指示进行设置版本:

版本:v API版本v(如果未指定,则默认为1)

标题是否可能包含API密钥,用户名和密码?用户名和密码不用于设置API密钥。

1 个答案:

答案 0 :(得分:2)

您似乎正在使用IG Labs REST Trading API;文档指出,有两种身份验证方式,具体取决于您指定的API版本。您引用的标头文档是所涉及的不同标头的总体概述。该部分对于实际了解该API的身份验证/授权的工作方式不是很有用。

在同一页面上是身份验证和授权部分,您需要研究的是该部分。这是描述两种认证方式的地方。还有一个separate examples section解释了两种不同的模式如何与显示的具体请求和响应一起工作。

要进行身份验证,您必须首先向/session route发送一个POST请求,并在X-IG-API-KEY标头中显示您的API密钥。这是您需要用户名和密码的地方。然后,有效的用户名/密码会为您提供安全令牌,用于后续请求。对于API版本1和2,可以包含一个附加字段encryptedPassword,以说明密码是纯文本还是加密的;否则,请参见图4。您只需要满足IG Singapore login restrictions,就可以安全地省略该字段。

对于v1和v2请求,您在响应头中获得了这些令牌,API版本v3在正文中提供了所需的信息。令牌的寿命有限。 v1 / v2令牌的有效期为6个小时,但是通过使用这些令牌进行请求后,它们会自动延长至72个小时,然后您需要再次登录。 v3令牌仅在60秒内有效。,但是单独的refresh_token可以通过将刷新令牌发送到/session/refresh-token endpoint来获得新令牌。

V1 / v2请求然后在/session响应中使用完全相同的标头中使用令牌,因此在CST(“客户端会话令牌”)和X-SECURITY-TOKEN标头之间进行复制而你在路上。

V3请求使用标准的OAuth Authorization标头,方法设置为Bearer。只需使用access_token结构中的oauthToken值构造该标头,并保存refresh_tokenaccess_token到期时为止。该文档还建议您设置IG-ACCOUNT-ID标头以标识帐户(令牌仅标识客户)。

我强烈建议您使用requests.Session() object简化标头处理。

对于API的v1和v2,请使用:

import requests

url = 'https://website.com'
API_KEY = '.... your API key ....'
username = 'username'
password = 'password'

session = requests.Session()
# these are sent along for all requests
session.headers['X-IG-API-KEY'] = API_KEY
# not strictly needed, but the documentation recommends it.
session.headers['Accept'] = "application/json; charset=UTF-8"

# log in first, to get the tokens
response = session.post(
    url + '/session',
    json={'identifier': username, 'password': password},
    headers={'VERSION': '2'},
)
response.raise_for_status()  # if not a 2xx response, raise an exception
# copy across the v1/v2 tokens
session.headers['CST'] = response.headers['CST']
session.headers['X-SECURITY-TOKEN'] = response.headers['X-SECURITY-TOKEN']

现在,您已设置为使用session继续访问API。

对于v3,令牌位于JSON主体中:

session = requests.Session()
# these are sent along for all requests
session.headers['X-IG-API-KEY'] = API_KEY

# log in first, to get the tokens
response = session.post(
    url + '/session',
    json={'identifier': username, 'password': password},
    headers={'VERSION': '3'},
)
response.raise_for_status()  # if not a 2xx response, raise an exception
response_data = response.json()
oauth_tokens = response_data['oauthToken']

session.headers['Authorization'] = 'Bearer ' + oauth_tokens['access_token']
session.headers['IG-ACCOUNT-ID'] = response_data['accountId']

现在,您已设置为使用session来继续访问API,直到经过oauth._tokens['expires_in']秒或给出401响应:

if response.status == 401 and response.json()['errorCode'] == 'error.security.oauth-token-invalid':
    # refresh required, old token is done.

然后您需要使用session.post(url + '/session/refresh-token', json={'refresh_token': oauth_tokens['refresh_token']}) to get a fresh oauthToken`结构:

# refresh the access token
del session.headers['Authorization']
response = session.post(
    url + '/session/refresh-token',
    json={'refresh_token': oauth_tokens['refresh_token']},
    headers={'VERSION': '1'},
)
response.raise_for_status()  # if not a 2xx response, raise an exception
oauth_tokens = response.json()

session.headers['Authorization'] = 'Bearer ' + oauth_tokens['access_token']

请注意,我会继续向每个单独的请求发送VERSION标头;他们的API使用版本号每个端点,因此/session有3个版本,但是/session/refresh-token仅具有版本1,您不能将VERSION设置为任何版本否则它会破坏。

V3 /session格式似乎比较麻烦,但是该版本可以让您无限期地刷新访问权限,前提是您在最后一次使用令牌后的10分钟内进行了刷新;无论您做什么,V1 / V2访问令牌都将在充值72小时后过期。