将CURL脚本转换为Python3 +请求

时间:2017-11-30 21:14:44

标签: php bash python-3.x curl python-requests

我有一个简短的CURL脚本,我正在尝试转换为Python,但我遇到了这么多麻烦。我的目标是一个需要格式为<public_key>.<sha256 hmac of url and body>的身份验证字符串的API。

我的遗留设置是一个简单的PHP脚本,它生成hmac并使用输出运行CURL命令。我正在尝试将其移植到Python以获得单独的项目。

传统代码:

hmac.php

<?php

$public = 'PUBLIC_KEY';
$private = 'PRIVATE_KEY';

$url = $argv[1];
$body = $argv[2];

$hmac = hash_hmac('sha256', $url . $body, $private, true);

print($public . '.' . base64_encode($hmac));

示例命令:

$ DATA='{"command": "say Just testing the API, ignore this..."}'
$ URL='https://website.url/api/user/<UUID>/command'
$ curl -X POST -d $DATA -H "Content-Type: application/json" -H "Authorization: Bearer $(php hmac.php $URL $DATA)" --url $URL

Python端口

到目前为止,我已经找到了如何为GET请求创建正确的hmac摘要,但是我在上面详述的POST请求时遇到了问题。

send_command.py:

def generate_bearer(pubkey, privkey, url, body):
    h = hmac.new(privkey.encode('utf8'), (url + body).encode('utf8'), sha256)
    encoded = b64encode(h.digest())
    return pubkey + '.' + encoded.decode('utf-8')

def send_command(server, command):
    target = '{}/server/{}/command'.format(url, server)
    data = {'command': command}

    bearer = generate_bearer(public, private, target, str(data))
    headers = {'Authorization': 'Bearer {}'.format(bearer),
               'content-type': 'application/json'}

    r = requests.post(target, headers=headers, data=data)

if __name__ == '__main__':
    print(send_command('<UUID>', 'say Just testing the API, ignore this...'))

据我所知,我需要将完整的JSON字符串传递给generate_bearer(),并将其作为我在请求中POST的数据。但是,使用此当前代码,我收到错误“请求的HMAC无效”。我在这里做错了什么?

3 个答案:

答案 0 :(得分:1)

很难说出你所描述的问题可能是什么。此API是否公开,以便其他人可以测试并获得更好的帮助?

我正在比较PHP与Python代码,并注意到您不遵循相同模式的URL:

  • PHP:answer / command
  • Python:target ='{} / server / {} / command'.format(url,server)

但由于这些例子不完整或脱离了背景,因此很难说清楚。

答案 1 :(得分:0)

经过一些实验,我发现了它。将数据dict传递给散列函数时,我使用的是str(data)。我为哈希和请求切换到json.dumps(data),现在一切正常。

新代码如下所示:

def send_command(server, command):
    target = '{}/server/{}/command'.format(url, server)
    d = {'command': command}

    bearer = generate_bearer(public, private, target, json.dumps(d))
    h = {'Authorization': 'Bearer {}'.format(bearer),
         'content-type': 'application/json'}

    r = requests.post(target, headers=h, data=json.dumps(d))

    return r.text

答案 2 :(得分:0)

我采用了示例here并将其转换为Python,如下所示:

import hmac
import hashlib
import base64

public = 'JkAFq7M47kLN0xVD';
private = 'E6X9FyZvMFeJbqtq.IwjlTuR.MKDoicB';

url = 'http://pterodactyl.app/api/admin/users';
body = '';

dig = hmac.new(private, msg='{}{}'.format(url, body), digestmod=hashlib.sha256).digest()

print '{}.{}'.format(public,  base64.b64encode(dig).decode()),

返回与PHP代码相同的输出:JkAFq7M47kLN0xVD.wgIxj + V8RHgIetcQg2lRM0PRSH / y5M21cPz9zVhfFaQ