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

查看:19
本文介绍了如何使用 HMAC-SHA512 和 Python requests 库签署 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:

密钥 - 您的 API 密钥.
签名 - 查询的 POST 数据根据 HMAC-SHA512 方法由您的密钥的秘密"签名.

Key - Your API key.
Sign - The query's POST data signed by your key's "secret" according to the HMAC-SHA512 method.

此外,所有查询都必须包含nonce"POST 参数.nonce 参数是一个整数,它必须始终大于前一个使用的 nonce.

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 文档(您在问题中引用),nonce 是 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摘要中使用的secret;您还可以传入不同的标题名称.

The argument passed in is the secret used in the HMAC digest; you can also pass in a different header name.

这篇关于如何使用 HMAC-SHA512 和 Python requests 库签署 POST 请求?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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