PHP中URL中特殊字符引起的问题(+,=) 分析及解决方法

PHP/Mysql Alice 3周前 (01-09) 41次浏览 0个评论

get 方法代码

function get($key = null, $default = null) {
	if (is_null($key)) {
		foreach ($_GET as $key => $val) {
			$_GET[$key] = trim(urldecode($val));
		}
		return $_GET;
	} else {
		$_GET[$key] = (isset($_GET[$key]) && $_GET[$key] != '') ? $_GET[$key] : $default;
		return trim(urldecode($_GET[$key]));
	}
}

登录验证代码

$input = \Util::get('data');
$data = json_decode(base64_decode($input), TRUE);
if ($this->do_verify($data) != 1){
    $output['msg'] = "登陆验证失败!";
    return (json_encode($output));
}

上述代码\Util::get(‘data’)接收到的 data 数据:

eyJ1aWQiOiIxMTc5NTIwNDA1MDAwNDI1IiwidWluIjoiQe 8h  8hyDkuIDliIDYgiIsInRva2VuIjoiQDE3MUA5MUAxNjNAODJAMTExQDg4QDExMEAxMDNAMTA1QDE1NkAxMDRAMTEwQDEwNkAxMDhAMTUyQDE0OUA4NkA5NkA4N0AxNzJAMTU5QDE0OUA5MEAxMTRAODNAMTAyQDEwM0AxMDhAMTExQDEwNEAxMDVAMTAzQDEwMEAxMDVAMTAxQDk2QDEwMUAxMDJAMTA3QDEwNEAxMDJAODlAOTdAOTFAMTY5QDE1NkAxNjFAMTUyQDg2QDExMEAxMDRAMTAzQDEwM0A5M0A5MEAxNTVAODNAMTExQDg4QDEwM0AxMDZAODVAMTgwIn0=

可以看到有两处分别有一个空格和两个空格,通过base64_decodejson_decode后,值成了 NULL,因此通不过后面的验证。

要怎么办呢,$data 这里肯定是不能改的,不然会影响绝大部分的登录,通不过验证的毕竟只是小部分,最好的方法就是在 if 里将获取的数据进一步处理,将特殊字符解析出来,既然接收的时候用了urldecode,那就将它用urlencode转回来吧

$input = urlencode($input);

urlencode转换后的数据:

eyJ1aWQiOiIxMTc5NTIwNDA1MDAwNDI1IiwidWluIjoiQe+8h++8hyDkuIDliIDYgiIsInRva2VuIjoiQDE3MUA5MUAxNjNAODJAMTExQDg4QDExMEAxMDNAMTA1QDE1NkAxMDRAMTEwQDEwNkAxMDhAMTUyQDE0OUA4NkA5NkA4N0AxNzJAMTU5QDE0OUA5MEAxMTRAODNAMTAyQDEwM0AxMDhAMTExQDEwNEAxMDVAMTAzQDEwMEAxMDVAMTAxQDk2QDEwMUAxMDJAMTA3QDEwNEAxMDJAODlAOTdAOTFAMTY5QDE1NkAxNjFAMTUyQDg2QDExMEAxMDRAMTAzQDEwM0A5M0A5MEAxNTVAODNAMTExQDg4QDEwM0AxMDZAODVAMTgwIn0%3D

仔细看,加号’+‘出来了
再用json_decode(base64_decode($input)), TRUE)处理$input 后发现还是 NULL,为什么呢,一步步分析,先查看base64_decode($input)是什么

{"uid":"1179520405000425","uin":"A'' 一刀؂","token":"@171@91@163@82@111@88@110@103@105@156@104@110@106@108@152@149@86@96@87@172@159@149@90@114@83@102@103@108@111@104@105@103@100@105@101@96@101@102@107@104@102@89@97@91@169@156@161@152@86@110@104@103@103@93@90@155@83@111@88@103@106@85@180"}7

这个 json 数据后面怎么会单独有个数字呀,一看就不对,怪不得 json_decode 后数据是 NULL,那这个 7 是如何来的呢,数据先是urlencode后再base64_decode,这里可以发现,urlencode后,使得原数据’=‘号变成了’%3D‘,进而造成base64_decode解析错误,所以使用urlencode还是不太正确的,那么究竟用什么来解决这一问题。

这就要讲到rawurldecode了,先来看下它的含义,

(PHP 4, PHP 5, PHP 7)

rawurldecode — 对已编码的 URL 字符串进行解码

说明
rawurldecode ( string $str ) : string
返回字符串,此字符串中百分号(%)后跟两位十六进制数的序列都将被替换成原义字符。

那么就来用下 rawurldecode 吧

$input = rawurldecode(urlencode($input));

再次查看$input 的值:

eyJ1aWQiOiIxMTc5NTIwNDA1MDAwNDI1IiwidWluIjoiQe+8h++8hyDkuIDliIDYgiIsInRva2VuIjoiQDE3MUA5MUAxNjNAODJAMTExQDg4QDExMEAxMDNAMTA1QDE1NkAxMDRAMTEwQDEwNkAxMDhAMTUyQDE0OUA4NkA5NkA4N0AxNzJAMTU5QDE0OUA5MEAxMTRAODNAMTAyQDEwM0AxMDhAMTExQDEwNEAxMDVAMTAzQDEwMEAxMDVAMTAxQDk2QDEwMUAxMDJAMTA3QDEwNEAxMDJAODlAOTdAOTFAMTY5QDE1NkAxNjFAMTUyQDg2QDExMEAxMDRAMTAzQDEwM0A5M0A5MEAxNTVAODNAMTExQDg4QDEwM0AxMDZAODVAMTgwIn0=

真相呼之欲出了,这里已经得到了正确的原数据,那么只要进一步优化验证逻辑,含有特殊字符的登录就走得通了,代码如下

$input = \Util::get('data');
$data = json_decode(base64_decode($input), TRUE);
if ($this->do_verify($data) != 1){
    //得到正确的登录数据
    $input = rawurldecode(urlencode(urldecode($input)));
    
    //将正确的登录数据再进行一次验证
    $data = json_decode(base64_decode($input),TRUE);
    if ($this->do_verify($data) != 1) {
        $output = "登陆验证失败!";
        return (json_encode($output));
    }
}

至此,特殊字符造成的解析问题解决完毕。


女程序员博客 , 版权所有丨本站采用BY-NC-SA协议进行授权 , 转载请注明PHP 中 URL 中特殊字符引起的问题(+,=) 分析及解决方法
喜欢 (1)
发表我的评论
取消评论
表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址