• ThinkPHP3.1URL分发BUG修正


    请先留意以下PHP脚本

    PHP脚本A(http://127.0.0.1:8110/test.php):

     1 $url = 'http://127.0.0.1:8110/demo.php';
     2 //curl请求
     3 $ch = curl_init();
     4 curl_setopt($ch, CURLOPT_URL, $url);
     5 curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
     6 curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 60);
     7 curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
     8 curl_setopt($ch, CURLOPT_POST, true);
     9 curl_setopt($ch, CURLOPT_POSTFIELDS, 'a=dwadwafadwadwadwa&m=dwadwa');
    10 $result = curl_exec($ch);
    11 var_dump($result);
    12 exit();

    PHP脚本B(127.0.0.1:8110/demo.php):

    1 var_dump("PHP input:" . file_get_contents('php://input'));
    2 var_dump("POST data:" . $_POST);

    执行脚本A的输出结果:

    string(81) "string(38) "PHP input:a=dwadwafadwadwadwa&m=dwadwa" string(15) "POST data:Array" "

    咦?为何会如此呢?

    其实在PHP跟其他编程语言一样,也是有它自己默认的输入流和输出流的。在Web环境下,输入流就是HTTP请求的POST的原始数据,输出流就是HTTP Body,在CLI环境下,就是当前标准的输入输出流(STDIN STDOUT)。而PHP的$_POST全局数组,则是从php://input中解析获得的。

    注意1:$HTTP_RAW_POST_DATA也能获取HTTP请求的POST的原始数据,但仅在碰到为识别的MIME类型时产生

    注意2:php://input和$HTTP_RAW_POST_DATA均不能在enctype="multipart/form-data"的表单提交下获得数据

    接着进入正题,可以看到ThinkPHP3.1的Lib/Core/Dispatcher.class.php有如下代码片段(约在233行):

     1     /**
     2      * 获得实际的操作名称
     3      * @access private
     4      * @return string
     5      */
     6     static private function getAction($var) {
     7         $action   = !empty($_POST[$var]) ?
     8             $_POST[$var] :
     9             (!empty($_GET[$var])?$_GET[$var]:C('DEFAULT_ACTION'));
    10         unset($_POST[$var],$_GET[$var]);

    在ThinkPHP中Lib/Core/Dispatcher.class.php充当了路由分发的功能(也可以叫前端控制器),这个类负责解析URL并根据约定和配置把后续请求交给指定的Controller和Action执行。

    一旦我们在开发中使用了依赖php://input读取请求数据的约定(如一些Flash上传插件,XML-RPC,内部接口服务等等),而刚好提交的数据(可能是二进制数据)又恰好被理解成 /&.+=.+/ 这类字符串,则会导致ThinkPHP出现莫名其妙的URL分发错误(失败)或请求的数据不完整的问题。

    而这都是因为ThinkPHP在分发过程中,先检查$_POST再检查$_GET,而且检查获取后又多此一举进行unset造成的。

    至此,Lib/Core/Dispatcher.class.php可以修改如下:

     1     /**
     2      * 获得实际的操作名称
     3      * @access private
     4      * @return string
     5      */
     6     static private function getAction($var) {
     7 //         $action   = !empty($_POST[$var]) ?
     8 //             $_POST[$var] :
     9 //             (!empty($_GET[$var])?$_GET[$var]:C('DEFAULT_ACTION'));
    10 //         unset($_POST[$var],$_GET[$var]);
    11         
    12         $action   = (!empty($_GET[$var])?$_GET[$var]:C('DEFAULT_ACTION'));        
    13         unset($_GET[$var]);        

    问题则解决。

    总结:该问题很难被发现,也难以定位原因,而且似乎只在ThinkPHP运行在 'URL_MODEL' => 0 模式下才发生。

  • 相关阅读:
    【u244】山地考察
    【u246】卫星照片
    【z08】乌龟棋
    【22.95%】【hdu 5992】Finding Hotels
    【t048】水流
    【b601】能量项链
    【b702】字符串的展开
    【a903】石子归并
    【9915】乘积最大
    JavaEE(24)
  • 原文地址:https://www.cnblogs.com/koboshi/p/4078608.html
Copyright © 2020-2023  润新知