CodeIgniter 2.2-Stable会话即将到期

时间:2014-11-27 11:08:57

标签: php codeigniter session codeigniter-2

在过去的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();
    }
}

1 个答案:

答案 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也会在那里更新。