PHP自动解码超全局变量 $_GET 和 $_REQUEST

在做一个网页分享微信好友、朋友圈的时候发现一个问题,就是分享的时候不带缩略图、没有网页描述,类似这个样子:

Snipaste_2018-04-09_13-34-56

因为是在移动端朋友圈分享,不是很容易定位问题,使用微信Web开发者工具调试,发现微信的JS-SDK有报错,提示:invalid signature,意思很明显,签名错误。然后开始排查签名错误的原因。关于微信分享的签名算法,可以查看官方文档

看了文档之后定位到问题出在页面当前URL和生成签名的时候不一致导致,当前页面URL是这样:

https://m.huanqiu.com/r/MV8wXzExNzY2ODQxXzI4Ml8xNTIyNzcyNDAw?pc_url=http%3A%2F%2Fopinion.huanqiu.com%2Feditorial%2F2018-04%2F11766841.html&from=groupmessage&isappinstalled=0

然后前端将此连接url encode之后发送给服务器获取签名,此时发送的URL变成

https%3A%2F%2Fm.huanqiu.com%2Fr%2FMV8wXzExNzY2ODQxXzI4Ml8xNTIyNzcyNDAw%3Fpc_url%3Dhttp%253A%252F%252Fopinion.huanqiu.com%252Feditorial%252F2018-04%252F11766841.html%26from%3Dgroupmessage%26isappinstalled%3D0 

然后服务端在处理的时候手动对$_GET['url']进行了url decode。此时这个URL变成了这样:

https://m.huanqiu.com/r/MV8wXzExNzY2ODQxXzI4Ml8xNTIyNzcyNDAw?pc_url=http://opinion.huanqiu.com/editorial/2018-04/11766841.html&from=groupmessage&isappinstalled=0

可以看到最终的这个URL和页面的URL是不一样的,导致invalid signature。查阅文档之后发现是出在了PHP代码的手动urldecode,因为PHP会对超全局变量 $_GET 和 $_REQUEST进行urldecode,对 $_GET 或 $_REQUEST 里的元素使用 urldecode() 将会导致不可预计和危险的结果。


参考:http://php.net/manual/zh/function.urldecode.php