如何在 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 - 他们会很乐意协助设置。
我正在尝试实施 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 - 他们会很乐意协助设置。