如何使用HMAC-SHA512和Python请求库签署POST请求? [英] How do I sign a POST request using HMAC-SHA512 and the Python requests library?

查看:270
本文介绍了如何使用HMAC-SHA512和Python请求库签署POST请求?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆