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&timestamp=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参数带&符号导致数据被截断的问题的主要内容,如果未能解决你的问题,请参考以下文章

POST数据中有特殊符号导致数据丢失的解决方法

idhttp提交post带参数并带上cookie

mod_rewrite 带问号和 & 符号(使用 PHP)

URI 中特殊字符处理

http、https请求URL中带有&等特殊字符的解决方法

Ajax入门