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);

以上只是临时处理方案,规范的解决办法还是两边统一编码解码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值