在过去的2 - 3年里,这是一个常见的问题,但我能够解决的修复似乎并不奏效。是否有人使用CI 2.2-stable(截至2014年10月29日)已经能够阻止会话频繁到期?
这就是我设置和检查会话的方式:
登录
// User session data
$user_session = array(
'user' => $user,
'start_time' => $_SERVER['REQUEST_TIME']
);
// Create user session
$this->session->set_userdata( $user_session );
MY_Controller由所有控制器继承,如果未找到会话,则重定向:
function __construct()
{
parent::__construct();
// Perform base check to make sure user is authenticated
if( !$this->session->userdata( 'user' ) )
{
// If not logged in then return server response 403 allowing redirect
// on the client-side using AngularJS interceptor
show_error('No valid authenticated session', 403);
}
} // END function __construct
所以我只检查会话数据是否存在,而不是直接使用session_id。通过存根Session.php库,它似乎进入sess_read()第135行,并且在检查第235行从数据库查询返回的num_rows()之前没有问题,然后它会破坏会话。
更新1
它似乎与此issue类似,总结得非常好here,但似乎仍然无法解决上面提到的问题here,其中提到了变化核心。但即便如此,这个解决方案对单页面应用程序也不起作用,因为会话将在所有服务器请求都是AJAX的情况下到期。
更新2
如果有人有任何建议或批评,我在下面添加了我的临时解决方案,但同样的问题仍然会发生,而不是经常发生。这是有道理的,因为标记为更新更新cookie的会话的传出请求可能同时发送请求,因为它不会在它们被处理之前更新而没有正确的cookie。它似乎只是将频率降低了一点点。可以通过设置心跳保持活动请求来进一步降低频率,该请求是更新会话的唯一请求,但它仍然不能解决问题的发生。
临时解决方案
使用更新中建议的修复程序,并利用我运行客户端的AngularJS。我最后添加了一个包含$ timeout的拦截器,它只在请求上每1小时附加一个自定义标头来更新会话,并将标头的检查添加到非SPA的建议修复中,它似乎工作
修复客户端
.factory('KeepAlive', ['$q', '$injector', '$timeout',
function( $q, $injector, $timeout ) {
var ticking = false;
var service = {
request: function( config ) {
if( ticking === false ) {
// Set ticking to block keep-alive
ticking = true;
// Set timeout to unblock keep-alive on expiry
$timeout( function() {
ticking = false;
}, 6300000 ); // 105 minute time out
// Add keep-alive header to out-going request
config.headers = { 'CodeIgniter': 'Keep-Alive' };
}
return config;
}
}
return service;
}])
修复服务器端
function sess_update()
{
// Check for AJAX request and keep-alive header before updating session
if( !$this->CI->input->is_ajax_request() &&
isset(apache_request_headers()['CodeIgniter']) )
{
return parent::sess_update();
}
}
答案 0 :(得分:0)
我正在使用CI 2.2并且会话工作正常,尽管我们在会话过期方面遇到了困难:
一个重要的考虑因素是CI经常重新生成session_id
以防止会话固定攻击。因此,不要直接在您的应用中使用session_id,而应将其视为CI内部使用的内容。为自己生成另一个id(这可能是第一个生成的session_id)并将其存储在会话用户数据中。只要会话本身未过期,会话数据就会保留。
if (!isset($this->session->userdata('sid')))
$this->session->set_userdata('sid', $this->session->userdata('session_id'));
有关会话到期的两个设置:
sess_expiration
:整个会话本身到期
sess_time_to_update
:session_id的到期和重新生成
如果要在数据库中存储会话,session_id也会在那里更新。