PHP由于服务器时间不正确导致的IE、Chrome下SESSION丢失

今天系统联调的时候遇到了一个比较奇怪的Bug,火狐下一切正常,切换到IE和Chrome之后发现一直是未登录状态。在确认了Ajax提交的登录一切正常后,把问题定位在了PHP Session是否正常设置上。

切换到项目的Session临时目录,删除所有的SESSION文件,使用IE打开页面。发现每次刷新一次都会新增一个SESSION文件。使用IE的开发者工具(按下F12唤出面板,菜单【缓存】->【查看Cookie信息】,如图)查看Cookie列表,发现PHP的Session确实没有写进去。

根据以往经验,PHP下SESSION丢失的问题,通常是因为在SESSION启动之前已经向服务器端发出了请求体,或者使用了与Session冲突的header(请参考:《PHP中Header位置错误导致SESSION丢失》一文),于是找到HTTP抓包工具进行抓包查看。HTTPLook是一款优秀的HTTP抓包软件,可以全局监听并且抓包HTTP协议,拥有丰富的功能,但是是收费版,无法直接在商业环境中使用,所以我选择了另外一款更加简单的嗅探器——MiniSniffer。设置下简单的过滤器,使其只显示目标站点的通讯。以下是截取的服务器应答头:

HTTP/1.1 200 OK
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Content-Type: text/html
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Server: Nginx/1.0.13
X-Powered-By: PHP/5.3.5
Set-Cookie: PHPSESSID=8644r5i0qn7nm74lmjhl2ptqh5; expires=Fri, 16-Mar-2012 16:36:35 GMT; path=/
Date: Sat, 17 Mar 2012 12:06:35 GMT 

正常情况下在创建SESSION ID的时候,Set-Cookie段是没有expires参数的,只有我们改变了设置SESSION过期时间才会出现这个参数。PHP代码如下:

session_set_cookie_params(3600);
session_start();

这里设置的Session ID的cookie过期时间为1小时。当时时间为上午10点半,也就是说,Set-Cookie段的expires被设置了一个过去的时间。时间标记里面GMT表示格林威治时间,和北京时间有8个小时的时差,换算过来大约是第二天凌晨2点左右。因此可以断定服务器慢了8小时左右。连上SSH,使用date命令查看当前时间,果然如此!

找到了原因,修复起来就容易了。使用date -s 来重新设置服务器时间。测试,OK,Bug Fixed。

这儿还是要说一下,在生产服务器上,为了保证时间的正确,请开启NTP服务,保持服务器时间的准确。

 

PHP由于服务器时间不正确导致的IE、Chrome下SESSION丢失》上有1条评论

  1. Pingback引用通告: PHP中Header位置错误导致SESSION丢失 – Starlight36's Blog

评论已关闭。