背景
最近发现有部分用户反馈,获取不到登录信息,于是进行分析
分析
我们的登录信息是加密存储到cookie中的,查看了下这个用户的 cookie加密信息中包含 加号“+” ,但是 php $_COOKIE 获取的时候,变成了空格,于是解密失败
分析请求头中的信息发现,请求传过来的值是有 “+” 的,但是 :
比如cookie中存储的 “cWEolyrQ0l63FG+YWHA” ,$_COOKIE 获取出来显示的 “cWEolyrQ0l63FG YWHA” ,多了一个空格
于是查找资料
找到如下介绍:
注释:在发送 cookie 时,setcookie 的值会自动进行 URL 编码。接收时会进行 URL 解码。如果你不需要这样,可以使用 setrawcookie() 代替。
注释:setrawcookie() 与 setcookie() 几乎完全相同,不同的是不会在发往客户机时,对 cookie 值进行自动 URL 编码。使用setrawcookie,不能使用这些字符内的值:(; \ t \ r \ n \ 013 \ 014)
看这个介绍,自己觉得取出来以后urldecode 一下就行了
urldecode($_COOKIE['user_id'])
实际是不行的,于是尝试 urlencode ,发现竟然成功了,但是如果cookie中有其他特殊字符 比如 "/" ,又不行了
urlencode($_COOKIE['user_id'])
所以这种方案,不能解决问题
解决方案
我们上面分析请求头中的cookie是完整的,所以我们可以尝试从请求头中获取cookie
<?php // getallheaders 是 apache支持的函数,nginx下需要自己定义 if (!function_exists('getallheaders')) { function getallheaders() { foreach ($_SERVER as $name => $value) { if (substr($name, 0, 5) == 'HTTP_') { $headers[str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5)))))] = $value; } } return $headers; } } $cookieStr = getallheaders()['Cookie']; $cookies = explode(';',$cookieStr); foreach($cookies as $cookie) { $cookieTmp = explode('=',$cookie); $_COOKIE[trim($cookieTmp[0])] = trim($cookieTmp[1]); }
其他解决办法
-
对cookie的值进行base64_encode(),拿来使用的时候再base64_decode()
参考