如何在 php 中验证 post 请求

How to authenticate a post request in php

我正在尝试实施 HTTP Post 身份验证,在本文档 https://www.clearslide.com/view/mail?iID=YS7LCS8XDPCABFR453DE 中提到,我无法理解我必须做些什么才能使它正常工作,我尝试了转储 $_REQUEST$_SERVER 变量。

这是我为此 $_REQUEST

得到的输出
Array
(
    [emailpitchsent] =>
)

这是 $_SERVER

的输出
Array
(
    [HTTP_HMAC] => D4L1ICmRMii32PdCryBkpSNdxY5XDxC_OXsDTEucyzU
    [HTTP_DATE] => Thu, 12 Nov 2015 00:50:05 PST
    [HTTP_SHA1] => GTRFkX7JYVtDQgvrQeXJmHaCF24=
    [CONTENT_LENGTH] => 262
    [CONTENT_TYPE] => application/json; charset=UTF-8
    [HTTP_HOST] => myhost.com
    [HTTP_CONNECTION] => Keep-Alive
    [HTTP_USER_AGENT] => Apache-HttpClient/4.5.1 (Java/1.7.0_55)
    [PATH] => /sbin:/usr/sbin:/bin:/usr/bin
    [SERVER_SIGNATURE] => <address>Apache/2.2.31 (Amazon) Server at myhost.com Port 80</address>

    [SERVER_SOFTWARE] => Apache/2.2.31 (Amazon)
    [SERVER_NAME] => myhost.com
    [SERVER_ADDR] => 0.0.0.0
    [SERVER_PORT] => 80
    [REMOTE_ADDR] => 0.0.0.1
    [DOCUMENT_ROOT] => /var/www/vhosts/myhost.com/httpdocs
    [SERVER_ADMIN] => info@myhost.com
    [SCRIPT_FILENAME] => /var/www/vhosts/myhost.com/httpdocs/clearslide.php
    [REMOTE_PORT] => 47400
    [GATEWAY_INTERFACE] => CGI/1.1
    [SERVER_PROTOCOL] => HTTP/1.1
    [REQUEST_METHOD] => POST
    [QUERY_STRING] => emailpitchsent
    [REQUEST_URI] => /clearslide.php?emailpitchsent
    [SCRIPT_NAME] => /clearslide.php
    [PHP_SELF] => /clearslide.php
    [REQUEST_TIME] => 1447318205
)

这是clearslide.php

的内容
<?php
$req_dump = print_r($_REQUEST, TRUE);
$ser_dump = print_r($_SERVER,TRUE);
$fp = fopen('request.log', 'a');
fwrite($fp, $req_dump);
fwrite($fp, $ser_dump);
fclose($fp);

我现在必须做什么才能让这个东西正常工作,我如何验证该请求并获取数据?

谢谢

您可以使用 file_get_contents('php://input')$HTTP_RAW_POST_DATA 获得原始 json body。以下是如何验证来自 headers 的签名的示例。此外,这是一个可以生成虚假测试请求的脚本。如果您还有任何问题,请告诉我。 :)

验证签名

<?php
// https://developers.google.com/api-client-library/java/google-http-java-client/reference/1.20.0/com/google/api/client/util/Base64#encodeBase64URLSafeString(byte[])
function urlsafe_b64encode($string) {
    $data = base64_encode($string);
    $data = str_replace(array('+','/', '='), array('-','_',''), $data);       
    return $data;
}

function extract_message(){
  $verb = $_SERVER["REQUEST_METHOD"];
  $sha1 = $_SERVER["HTTP_SHA1"];
  $content_type = $_SERVER["CONTENT_TYPE"];
  $request_time = $_SERVER["HTTP_DATE"];
  $path = parse_url($_SERVER["REQUEST_URI"], PHP_URL_PATH);     
  return "$verb\n$sha1\n$content_type\n$request_time\n$path";
}

function calculate_signature($to_sign, $api_key) {
  return urlsafe_b64encode(hash_hmac('sha256', $to_sign, $api_key, true));
}

function get_recieved_signature() { return $_SERVER["HTTP_HMAC"]; }

function verify_signature($recieved, $calculated) { return $recieved == $calculated; }

$api_key = "apikey";

$to_sign = extract_message();
$calculated_signature = calculate_signature($to_sign, $api_key);
$recieved_signature = get_recieved_signature();
$matched = verify_signature($recieved_signature, $calculated_signature);

$json_obj = json_decode(file_get_contents('php://input'), TRUE);

$fp = fopen('request.log', 'a');
fwrite($fp, print_r(array(
  '$_SERVER' => $_SERVER, 
  "JSON" => $json_obj,
  "SIGNATURE INFO" =>  array(
    "To Sign" => str_replace("\n", "\n", $to_sign),
    "Received" => $recieved_signature,
    "Calculated" => $calculated_signature,
    "Matched" => $matched ? "TRUE" : "FALSE"
  )
), TRUE));
fclose($fp);

索取样品

<?php
// https://developers.google.com/api-client-library/java/google-http-java-client/reference/1.20.0/com/google/api/client/util/Base64#encodeBase64URLSafe(byte[])
function urlsafe_b64encode($string) {
    $data = base64_encode($string);
    $data = str_replace(array('+','/','='), array('-','_',''), $data);
    return $data;
}

$sample_json = '{"company":"Example, Inc","pitchDetailsLink":"https://dev.clearslideng.com/manage/email/details?userVID=6YSZ9BBJWVM3H87PUAPE","senderEmail":"tester@clearslide.com","time":"Fri, 11/13/2015, 10:19 AM PST","recipients":["my@example.com"],"decks":["testing"]}';

$api_endpoint = 'http://localhost';

$verb = "POST";
$sha1 = base64_encode(sha1($sample_json));
$content_type = "application/json; charset=UTF-8";
$request_time = date("D, d M Y H:i:s T");
$path = "/emailpitchsent";

$to_sign = "$verb\n$sha1\n$content_type\n$request_time\n$path";
$api_key = "apikey";
$signature = urlsafe_b64encode(hash_hmac('sha256', $to_sign, $api_key, true));

$ch = curl_init("$api_endpoint$path");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// curl_setopt($ch, CURLOPT_VERBOSE, 1);
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
 "CONTENT-TYPE: $content_type",
 "HMAC: $signature",
 "DATE: $request_time",
 "SHA1: $sha1"
));
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $sample_json);
$result = curl_exec($ch);
curl_close($ch);

echo "To Sign: ". str_replace("\n", "\n", $to_sign) ."\n\n";
echo "Response: \n\n$result";

示例日志

Array
(
    [$_SERVER] => Array
        (
            [USER] => vagrant
            [HOME] => /home/vagrant
            [FCGI_ROLE] => RESPONDER
            [QUERY_STRING] => event=emailpitchsent
            [REQUEST_METHOD] => POST
            [CONTENT_TYPE] => application/json; charset=UTF-8
            [CONTENT_LENGTH] => 270
            [SCRIPT_FILENAME] => /vagrant/public/index.php
            [SCRIPT_NAME] => /index.php
            [REQUEST_URI] => /index.php?event=emailpitchsent
            [DOCUMENT_URI] => /index.php
            [DOCUMENT_ROOT] => /vagrant/public
            [SERVER_PROTOCOL] => HTTP/1.1
            [GATEWAY_INTERFACE] => CGI/1.1
            [SERVER_SOFTWARE] => nginx/1.1.19
            [REMOTE_ADDR] => 10.0.0.10
            [REMOTE_PORT] => 61094
            [SERVER_ADDR] => 10.0.0.200
            [SERVER_PORT] => 80
            [SERVER_NAME] => 192.168.22.10.xip.io
            [HTTPS] => off
            [REDIRECT_STATUS] => 200
            [LARA_ENV] => local
            [HTTP_HMAC] => vnQM9g41jE--rJvvwymezRY5VU9pf52Vu9sGhe_Gy-4
            [HTTP_DATE] => Thu, 19 Nov 2015 06:24:49 PST
            [HTTP_SHA1] => X7hjTy8DUzIUNO05JiuXp1DT3Js=
            [HTTP_CONTENT_LENGTH] => 270
            [HTTP_CONTENT_TYPE] => application/json; charset=UTF-8
            [HTTP_HOST] => 10.0.0.200
            [HTTP_CONNECTION] => Keep-Alive
            [HTTP_USER_AGENT] => Apache-HttpClient/4.5.1 (Java/1.7.0_91)
            [PHP_SELF] => /index.php
            [REQUEST_TIME] => 1447943089
        )

    [JSON] => Array
        (
            [company] => ClearSlide
            [pitchDetailsLink] => https://dev.clearslideng.com/manage/email/details?userVID=YGCD4WNJT377FQ6FTUFH
            [senderEmail] => tester@clearslide.com
            [time] => Thu, 11/19/2015, 6:24 AM PST
            [recipients] => Array
                (
                    [0] => test@example.com
                )

            [decks] => Array
                (
                    [0] => RockyBeach-720
                )

        )

    [SIGNATURE INFO] => Array
        (
            [Path] => /index.php
            [To Sign] => POST\nX7hjTy8DUzIUNO05JiuXp1DT3Js=\napplication/json; charset=UTF-8\nThu, 19 Nov 2015 06:24:49 PST\n/index.php
            [Received] => vnQM9g41jE--rJvvwymezRY5VU9pf52Vu9sGhe_Gy-4
            [Calculated] => vnQM9g41jE--rJvvwymezRY5VU9pf52Vu9sGhe_Gy-4
            [Matched] => TRUE
        )

)

服务器端签名示例

POST
X7hjTy8DUzIUNO05JiuXp1DT3Js=
application/json; charset=UTF-8
Thu, 19 Nov 2015 06:24:49 PST
/index.php

Clearslide.com 为所有用户提供免费技术支持。您可能想尝试向他们发送电子邮件至 support@clearslide.com - 他们会很乐意协助设置。