ci框架session失效问题解决
2018-05-28
后端
场景如下,用户注册后,后台调用登录方法,写好session,再跳转到用户信息页,用户信息页发现没有session时,跳到登录页.
简单明了,但,妈蛋的...出错了...在到用户信息页时,SESSION不见了...
1.先在用户页(user/info)输出了一下SESSION,发现没有,又在注册(user/segist)结束时,输出SESSION,发现还没有,我靠......
2.看CI的SESSION类,system/libraries/Session.php,发现用的不是$_SESSION,用的是COOKIE,好吧...
3.重新在用户信息页输出COOKIE,发现没有,正常,如果这里有,程序就不会出错了,接着在注册页输出,还没有...想了一下,这也正常,COOKIE本来第一次就不能用,另写一个方法(user/coco),里面只写var_dump($_COOKIE),这时,COOKIE出现了.
4.既然COOKIE没问题,为什么会造成丢失的情况,再在新的页面里调用原先的登录函数,这时问题出现了,COOKIE不见了,再刷新一次,又出现了,但值不同,这里详细说一下.
原先给CI的session赋值,是用$this->session->set_userdata(array('abc'=>123));,此时,COOKIE里面的值不仅仅是userId,还包括一些浏览器的信息,如下
array(1){
["ci_session"]=>
string(338)"a:6:{s:10:"session_id";s:32:"3a6bf659f536ae6fbca58e7c9ad458a2";s:10:"ip_address";s:14:"192.168.168.11";s:10:"user_agent";s:102:"Mozilla/5.0(Windows NT 6.1)AppleWebKit/537.36(KHTML, like Gecko)Chrome/34.0.1847.137Safari/537.36";s:13:"last_activity";i:1400467260;s:9:"user_data";s:0:"";s:3:"abc";i:123;}790950aa8c5140e0cbbd3b197163f7dc"
}
此时,刷新新页面user/coco,发现cookie变成了只有abc=>123,其他信息全没了.明显是和我的登录方法有关,但就算如些,理论上也应该可以用$this->session->userdata('abc')取出值来,但结果是为空.
在这期间,写了无数个var_dump(),在这里就不多说了,直接说结果,在Session类中的构造方法里,有一个这个判断
if(! $this->sess_read())
{
$this->sess_create();
}
else
{
$this->sess_update();
}
意思是如果能读出数据,就只对原有的COOKIE进行更新操作,如果没有,则新建一个,这里所指的有没有,是针对下标ci_session的.
sess_read()中,有多处判断COOKIE是否合法,其中
if(! is_array($session) OR ! isset($session['session_id']) OR ! isset($session['ip_address']) OR ! isset($session['user_agent']) OR ! isset($session['last_activity']))
{
$this->sess_destroy();
return FALSE;
}
这段是判断COOKIE中是否有这些值,如果没有,CI会认为这个COOKIE不合法,从而新建一个.
那为什么我的COOKIE中会没有这些值呢,原来是在我的登录方法中,调用了$this->session->sess_destroy()这个方法,把所有的COOKIE全销毁,然后又跟着调用了$this->session->set_userdata()进行赋值,这时,之前的浏览器信息被销毁,新赋值的数据确还在.但在Session类中,又会判断这样不合法,所以又会重新创建一个新的,这样刚刚赋值的数据又会被删掉,所以,自动登录失败.
解决方法是在销毁原先的COOKIE后,手工新建一个,再赋值新的数据.
//设置登录状态
publicfunction setLogin($userInfo)
{
$this->session->sess_destroy();
$this->session->sess_create();
$this->session->set_userdata(array('userId'=>trim($userInfo['UserID'])));
}// end func
总结:
这个问题,我想不通应该怪我还是怪CI...如果说怪我,我感觉我的逻辑没什么错,重新登录前销毁之前的用户记录(如果这个逻辑不对,请大神指教);如果说怪CI,其实它也没什么错...但就是错了...可能销毁的时候,加一个选择性的就更好了,是只销毁用户数据,还是销毁全部
最后,这个故事告诉我们,会var_dump是多么的重要啊!!