请先留意以下PHP脚本

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

 $url = 'http://127.0.0.1:8110/demo.php';
//curl请求
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 60);
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, 'a=dwadwafadwadwadwa&m=dwadwa');
$result = curl_exec($ch);
var_dump($result);
exit();

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

 var_dump("PHP input:" . file_get_contents('php://input'));
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行):

     /**
* 获得实际的操作名称
* @access private
* @return string
*/
static private function getAction($var) {
$action = !empty($_POST[$var]) ?
$_POST[$var] :
(!empty($_GET[$var])?$_GET[$var]:C('DEFAULT_ACTION'));
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可以修改如下:

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

问题则解决。

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

ThinkPHP3.1URL分发BUG修正的更多相关文章

  1. Bug修正

    名称:nice! 项目名称:约跑app 组长:李权 成员:韩媛媛 刘芳芳 宫丽君 于淼 Bug修正: 1.我看到的现象:退出当前的账号后,按返回键可以再次进入登录界面. 期待的现象:能够安全登陆和退出 ...

  2. HubbleDotNet 最新绿色版,服务端免安装,基于eaglet 最后V1.2.8.9版本开发,bug修正,支持一键生成同步表

    HubbleDotNet 是一个基于.net framework 的开源免费的全文搜索数据库组件.开源协议是 Apache 2.0.HubbleDotNet提供了基于SQL的全文检索接口,使用者只需会 ...

  3. Lazarus下面的javascript绑定另外一个版本bug修正

    Lazarus下面的javascript绑定另外一个版本bug修正 从svn 检出的代码有几个问题 1.fpcjs.pas 单元开始有 {$IFDEF FPC} {$MODE delphi} {$EN ...

  4. 王者荣耀交流协会互评Beta版本及答复功能改进建议、Bug修正

    互评Beta版本 欢迎来怼团队博客园安卓APP Thunder团队爱阅app 探路者团队贪吃蛇 Hello World!团队项目空天猎 答复功能改进建议 答复其他各组给出的“就现有技术和工作量,不改变 ...

  5. ThinkPHP3.1在多数据库连接下存储过程调用bug修正

    最近使用ThinkPHP3.1进行一个项目的开发,由于该项目需要连接多台不同的数据库,所以使用如下配置方法: <?php return array( //'配置项'=>'配置值' //数据 ...

  6. NVelocity-0.4.2.8580 的修改记录[发个vs2008能用的版本] -- "It appears that no class was specified as the ResourceManager..." bug 修正等

    因为另有开发记录工具最新没怎么在 cnblog 写开发备忘.不过我觉得这个是个比较严重的问题,觉得有必要让更多的人知道处理方法,所以在 cnblog 也放上一篇希望广为传播. 因为现在网络上vs200 ...

  7. [算法 笔记]2014年去哪儿网 开发笔试(续)第一题BUG修正

    上一篇的blog地址为:http://www.cnblogs.com/life91/p/3313868.html 这几天又参加了一个家公司的笔试题,在最后的编程题中竟然出现了去哪儿网开发的第一题,也就 ...

  8. KEIL CRACK及 0xFD Bug修正方法

    0xFD Bug是keil编译器中始终存在,而又从未得到官方修复的一个BUG!!! BUG描述:当C源代码中使用了汉字等非ASCII字符,而此字符的编码又恰好包含了大于或等于0xFD的字节时,这个字节 ...

  9. C++ Primer第18章Vector的再实现及bug修正

    C++Primer第18.1.2节在介绍allocator类的时候,给了一个仿照标准库中vector的例子.感觉示例代码非常好,但是本人发现了一个bug,与大家共享. 按照作者的示例程序,编译程序时总 ...

随机推荐

  1. P2P通信标准协议(三)之ICE

    在P2P通信标准协议(二)中,介绍了TURN的基本交互流程,在上篇结束部分也有说到,TURN作为STUN 协议的一个拓展,保持了STUN的工具性质,而不作为完整的NAT传输解决方案,只提供穿透NAT的 ...

  2. JAVA常见算法题(八)

    package com.xiaowu.demo; /** * 求s=a+aa+aaa+aaaa+aa...a的值,其中a是一个数字.例如2+22+222+2222+22222(此时共有5个数相加), ...

  3. XShell命令行使用

    1.建立连接: 2.查看总体目录: 3.查看对应服务目录: 4.删除对应jar包后,再查看目录下文件: 5.上传对应的jar文件: 6.重启服务 7.查看服务日志: 8.mv old-name new ...

  4. 【AS3 Coder】任务五:Flash 2D游戏的第二春(中)

    在上一节中,我们介绍了如何构建我们小小的90度角RPG游戏的背景,在这一节中我将为列位带来重头戏部分,隆重介绍我们的主角及NPC登场,噔噔噔噔……掌声在哪里?! 额,没听到掌声,罢了,直接开场吧. 本 ...

  5. ElasticSearch文档

    1.什么是文档? 程序中大多的实体或对象能够被序列化为包含键值对的JSON对象,键(key)是字段(field)或属性(property)的名字,值(value)可以是字符串.数字.布尔类型.另一个对 ...

  6. java源码阅读String

    1类签名与注释 public final class String implements java.io.Serializable, Comparable<String>, CharSeq ...

  7. bitcoin-qt忘记密码

    客户端有钱包加密功能,输入密码可以增强安全性. 但是,如果你把钱包文件弄丢了,那即使设了密码,币也会丢. 关闭bitcoin-qt,把钱包文件wallet.dat 剪到其他地方(但不要删除),然后重新 ...

  8. 自己定义控件-LinearListView

    一.描写叙述 用LinearLayout 实现的一个ListView ,重写了ListView中的经常使用函数,所以使用起来和ListView 没有区别. 比方:setAdapter.addHeade ...

  9. JAVA反射机制--怎么不受泛型束缚给数组赋值

    在Java中,声明数组的时候我们经常会写泛型限制用户输入或者获取的数据.如:ArrayList<String> list = new ArrayList<>(); String ...

  10. 迁移Veil:手工打造Windows下编译的免杀Payload

    作者:RedFree 本文转自乌云 Veil对Payload的免杀已经做的很好了,最新的Veil有39个可用的Payload.但是有时候需要使用Windows来完成所有的渗透测试工作,Linux和Wi ...