PHP处理POST参数带&符号导致数据被截断的问题
Posted SuperAvalon
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了PHP处理POST参数带&符号导致数据被截断的问题相关的知识,希望对你有一定的参考价值。
如果API接口的参数数据中,出现&符号,php在处理POST数据时,则会自动截断数据流,导致该参数的数据不完整,并且新增一个并不受欢迎的参数,进而导致延签失败,接口拿不到期望的数据等异常。
比如:
curl "https://www.example.com/index.php" -d 'money=69.0&order_name=0010195102246107133&products=["discount":49,"num":1,"price":118,"product_name":"乐家特级初榨橄榄油&摩典纳香醋礼盒装500ml*2","product_no":"21562075"]&qrcode_str=6226158790233247708&score_money=69.0&service=user.cutMoney&source=cityshop×tamp=1578378620686&type=1&version=1.0&sign=bde2e7224f804d24767bdc817dd0fee6'
打印$_POST,获取到的数据是:
array (
'money' => '69.0',
'order_name' => '0010195102246107133',
'products' => '["discount":49,"num":1,"price":118,"product_name":"乐家特级初榨橄榄油',
'摩典纳香醋礼盒装500ml*2","product_no":"21562075"]' => '',
'qrcode_str' => '6226158790233247708',
'score_money' => '69.0',
'service' => 'user.cutMoney',
'source' => 'cityshop',
'timestamp' => '1578378620686',
'type' => '1',
'version' => '1.0',
'sign' => 'bde2e7224f804d24767bdc817dd0fee6',
)
以上数据,显然是我们不愿意看到的。
上面示例请求报文中,发现参数products为json数据,且里面字段product_name带有&符,遇到此问题,通常做法是,运用base64编码对特殊报文进行编码,请求方编码,接口方解码,这是规范的处理流程。
但具体实践中,如果请求方不方便做系统升级,诸如app、收银机系统等,那么我们只能通过后端来处理此类棘手问题,
思路:我们应该想到使用正则来处理请求参数,避免使用$_POST全局变量或系统框架提供的参数来处理请求数据;
方案一:
为接口参数定义正则表达式,通过正则去获取参数,优点是可以按照现有参数列表获取正确的参数值,但接口增减参数,需要配合修改,否则会报错
<?php
$stream = file_get_contents("php://input");
$args = ['money' => '(.*?)&', 'order_name' => '(.*?)&', 'products' => '(\\[.*?\\])&', 'qrcode_str' => '(.*?)&', 'score_money' => '(.*?)&', 'service' => '(.*?)&', 'source' => '(.*?)&', 'timestamp' => '(.*?)&', 'type' => '(.*?)&', 'version' => '(.*?)&', 'sign' => '(.*?$)'];
foreach ($args as $arg => $pattern)
if (preg_match('/'.$arg.'='.$pattern.'/', $stream, $matches))
$args_param[$arg] = $matches[1];
else
$args_param[$arg] = '';
if ($args_param['service'] == 'user.cutMoney')
$post_param = $args_param;
else
$post_param = $_POST;
var_dump($post_param);
方案二:
单独处理带有&符的参数,并且unset掉异常的参数,优点是,不影响接口增减参数,但异常参数可能处理不干净,比如这样一个字符串
乐家特级初榨橄榄油&bug_test&摩典纳香醋礼盒装500ml*2,
如遇到这类的字符流,则会新增一个看似规范的bug_test参数,导致系统难以发现它,
<?php
$post_param = $_POST;
if ($post_param['service'] == 'user.cutMoney')
if (preg_match('/products=(\\[.*?\\])&/', $stream, $matches))
$post_param['products'] = $matches[1];
foreach ($post_param as $key => $val)
if(strpos($key, "]") || strpos($key, ""))
unset($post_param[$key]);
var_dump($post_param);
以上只是临时处理方案,规范的解决办法还是两边统一编码解码
以上是关于PHP处理POST参数带&符号导致数据被截断的问题的主要内容,如果未能解决你的问题,请参考以下文章