Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/461.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript Python POST请求相同的JS/PHP_Javascript_Php_Python_Http Post - Fatal编程技术网

Javascript Python POST请求相同的JS/PHP

Javascript Python POST请求相同的JS/PHP,javascript,php,python,http-post,Javascript,Php,Python,Http Post,我不擅长js/php,但我需要将下面的代码转换为Python Javascript版本: function api_query(key,keyId,url,post,body,signature,cb){var method='POST'; var date=new Date(); var content_type='application/x-www-form-urlencoded; charset=UTF-8;'; var body_md5=CryptoJS.MD5(

我不擅长js/php,但我需要将下面的代码转换为Python

Javascript版本:

function api_query(key,keyId,url,post,body,signature,cb){var method='POST';
    var date=new Date();
    var content_type='application/x-www-form-urlencoded; charset=UTF-8;';
    var body_md5=CryptoJS.MD5(body);
    var http= new XMLHttpRequest();http.onreadystatechange=function(){if (http.readyState===4){cb(JSON.parse(http.responseText));}};
    http.open("POST",'http://'+url,true);http.setRequestHeader('x-pbx-date',date);
    http.setRequestHeader('Accept','application/json');
    http.setRequestHeader('Content-Type',content_type);
    http.setRequestHeader('Content-MD5',body_md5);
    http.setRequestHeader('x-pbx-authentication',keyId+':'+signature);
    http.send(body);}
PHP版本:

    $post = http_build_query($post);
    $content_type = 'application/x-www-form-urlencoded';
    $content_md5 = hash('md5', $post);
    $signature = base64_encode(hash_hmac('sha1', $method."\n".$content_md5."\n".$content_type."\n".$date."\n".$url."\n", $secret_key, false));
    $headers = array('Date: '.$date, 'Accept: application/json', 'Content-Type: '.$content_type, 'x-pbx-authentication: '.$key_id.':'.$signature, 'Content-MD5: '.$content_md5);

    if (isset($opt['secure']) && $opt['secure']){
        $proto = 'https';
    }else{
        $proto = 'http';
    }
    $ch = curl_init($proto.'://'.$url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    curl_setopt($ch, CURLOPT_TIMEOUT, 60);
    $res = json_decode(curl_exec($ch), true);
    if ($res){return $res;}else{return false;}
我已尝试请求库:

headers = {
    'x-pbx-date': date,
    'Content-Type': content_type,
    'Content-MD5': body_md5_str,
    'x-pbx-authentication': signature,
}
payload = {
    'date_from': date_from,
    'date_to': date_to,
}
r = requests.post(url, data=json.dumps(payload), headers=headers)
httlib2:

http = httplib2.Http()
response, content = http.request(url, 'POST', headers=headers, body=urllib.urlencode(payload))
urllib2:

req = urllib2.Request(url, data=urllib.urlencode(payload), headers=headers)
response = urllib2.urlopen(req).read()

什么都不管用。在每个重试服务器响应中:未验证。有什么想法吗

嗯,我想你的问题是身份验证。您没有在Python中演示如何做到这一点,但我想这是有点道理的,因为您在创建主体(
json.dumps
call)之前就以某种方式计算了
body\u md5\u str
signature
),所以它一定有问题。您是否确保您的代码生成与JS和PHP代码相同的值

就个人而言,我将实现一个身份验证类,该类将在请求触发之前添加必要的头。有关详细信息,请参阅,以下是我的(未经测试)尝试,如果我掌握了正确的详细信息:

import requests
import hashlib
import hmac
import base64
from wsgiref.handlers import format_date_time
import datetime
from time import mktime

CONTENT_TYPE_FORM_URLENCODED = "application/x-www-form-urlencoded"

class OnlinePBXAuth(requests.auth.AuthBase):
    def __init__(self, key_id, secret):
        self.key_id = key_id
        self.secret = secret

    def __call__(self, r):
        content_type = r.headers.get("Content-Type", CONTENT_TYPE_FORM_URLENCODED)
        body = r.body or ""
        body_md5 = hashlib.md5(body).hexdigest()
        date = format_date_time(mktime(datetime.datetime.now().timetuple()))
        date = r.headers.get("Date", date)
        r.headers["Date"] = date
        r.headers["X-PBX-Date"] = date
        sign = "\n".join([r.method, body_md5, content_type, date, r.url, ""])
        signature = base64.b64encode(hmac.new(self.secret, sign, hashlib.sha1).hexdigest())
        r.headers["Content-MD5"] = body_md5
        r.headers["X-PBX-Authentication"] = "{0}:{1}".format(self.key_id, signature)
        return r
这不是最漂亮的代码,但我想这应该能奏效

然后,像这样使用它:

auth = OnlinePBXAuth(KEY_ID, KEY_SECRET)
...
data = {"date_from": date_from, "date_to": date_to}
r = requests.post(url, data, auth=auth)
...
session = requests.Session(auth=OnlinePBXAuth(KEY_ID, KEY_SECRET))
...
r1 = session.post(url, data)
...
r2 = session.post(another_url, another_data)
或者甚至像这样:

auth = OnlinePBXAuth(KEY_ID, KEY_SECRET)
...
data = {"date_from": date_from, "date_to": date_to}
r = requests.post(url, data, auth=auth)
...
session = requests.Session(auth=OnlinePBXAuth(KEY_ID, KEY_SECRET))
...
r1 = session.post(url, data)
...
r2 = session.post(another_url, another_data)

我不确定它是否适用于空体请求(像大多数GET一样)和多部分分块体(因此请自行考虑或尽量避免这些),但我认为它适用于application/x-www-form-urlencoded和application/json编码的数据。

是,我绝对确保我的代码生成与php/js等同等的值。我通过Chrome一步一步地调试找到了它。相同的md5哈希和签名。您的代码返回:
{“状态”:0,“注释”:“未验证”,“数据”:“}
Hmm。。。那我猜我错了。很抱歉不幸的是,我没有发现代码有任何问题。嗯,有一个服务可以显示向它发出的HTTP请求。也许值得尝试将PHP和Python程序(具有固定日期,因此请求将完全相同)都指向那里,并将请求与相同的数据进行比较?也许这会给Python版本带来一些线索。Ogh,在我的代码中生成的签名str中曾经有一个“\n”符号。包括你的工作在内的所有方法。我需要帮助。