如何使用HMAC-SHA512和Python请求库签署POST请求? [英] How do I sign a POST request using HMAC-SHA512 and the Python requests library?
问题描述
我正在尝试使用Python访问poloniex.com(一种加密货币交易所)上的交易API.为此,我必须遵循以下处方:
I'm trying to use Python to access the trading API at poloniex.com, a cryptocurrency exchange. To do this I must follow this prescription:
所有对交易API的调用都通过HTTP POST发送到 https://poloniex.com/tradingApi 和必须包含以下标头:
All calls to the trading API are sent via HTTP POST to https://poloniex.com/tradingApi and must contain the following headers:
Key-您的API密钥.
签名-根据HMAC-SHA512方法,由您的键的秘密"对查询的POST数据进行签名.
Key - Your API key.
Sign - The query's POST data signed by your key's "secret" according to the HMAC-SHA512 method.
此外,所有查询都必须包含"nonce" POST参数.随机数参数是一个整数,必须始终大于使用的上一个随机数.
Additionally, all queries must include a "nonce" POST parameter. The nonce parameter is an integer which must always be greater than the previous nonce used.
这是我到目前为止所拥有的.我当前的问题是,我不知道如何编译POST URL,以便可以在不先发送不完整请求的情况下对其进行签名.这显然行不通.
Here is what I have so far. My current issue is that I do not know how to compile the POST url so that it can be signed without sending the incomplete request first. This obviously doesn't work.
import requests
import hmac
import hashlib
import time
headers = { 'nonce': '',
'Key' : 'myKey',
'Sign': '',}
payload = { 'command': 'returnCompleteBalances',
'account': 'all'}
secret = 'mySecret'
headers['nonce'] = int(time.time())
response = requests.post( 'https://poloniex.com/tradingApi', params= payload, headers= headers )
headers['Sign'] = hmac.new( secret, response.url, hashlib.sha512)
推荐答案
Create a prepared request; you can add headers to that after the body has been created:
import requests
import hmac
import hashlib
request = requests.Request(
'POST', 'https://poloniex.com/tradingApi',
data=payload, headers=headers)
prepped = request.prepare()
signature = hmac.new(secret, prepped.body, digestmod=hashlib.sha512)
prepped.headers['Sign'] = signature.hexdigest()
with requests.Session() as session:
response = session.send(prepped)
我将您的params
自变量更改为data
;对于POST请求,习惯上是在正文中发送参数,而不是在URL中发送.
I changed your params
argument to data
; for a POST request it is customary to send the parameters in the body, not the URL.
对于随机数,我将使用 itertools.count()
对象,从当前时间开始播种,因此重新启动不会对其造成影响.根据 Poloniex API文档(您在问题中引用的内容),随机数是POST正文,而不是标题,因此将其放在payload
字典中:
For the nonce, I'd use a itertools.count()
object, seeded from the current time so restarts don't affect it. According to the Poloniex API documentation (which you quoted in your question), the nonce is part of the POST body, not the headers, so put it in the payload
dictionary:
from itertools import count
import time
# store as a global variable
NONCE_COUNTER = count(int(time.time() * 1000))
# then every time you create a request
payload['nonce'] = next(NONCE_COUNTER)
如果您每秒创建多个请求,则使用int(time.time())
将重复使用相同的号码. Poloniex提供的示例代码使用int(time.time()*1000)
使得每微秒创建一个请求成为可能,但是使用您自己的单调递增计数器(从time.time()
播种)更加健壮.
Using int(time.time())
would re-use the same number if you created more than one request per second. The example code provided by Poloniex uses int(time.time()*1000)
to make it possible to create a request every microsecond instead, but using your own monotonically increasing counter (seeded from time.time()
) is far more robust.
您还可以将摘要签名过程封装在自定义身份验证中对象;这样的对象将在准备好的请求中传递,作为准备工作的最后一步:
You can also encapsulate the digest signing process in a custom authentication object; such an object is passed in the prepared request as the last step in preparation:
import hmac
import hashlib
class BodyDigestSignature(object):
def __init__(self, secret, header='Sign', algorithm=hashlib.sha512):
self.secret = secret
self.header = header
self.algorithm = algorithm
def __call__(self, request):
body = request.body
if not isinstance(body, bytes): # Python 3
body = body.encode('latin1') # standard encoding for HTTP
signature = hmac.new(self.secret, body, digestmod=self.algorithm)
request.headers[self.header] = signature.hexdigest()
return request
将其与您的requests
通话一起使用:
Use this with your requests
calls:
response = requests.post(
'https://poloniex.com/tradingApi',
data=payload, headers=headers, auth=BodyDigestSignature(secret))
传入的参数是HMAC摘要中使用的秘密;您还可以传入其他标题名称.
The argument passed in is the secret used in the HMAC digest; you can also pass in a different header name.
这篇关于如何使用HMAC-SHA512和Python请求库签署POST请求?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!