【问题标题】:Avoid session timeout reset when sending ajax request发送ajax请求时避免会话超时重置
【发布时间】:2020-12-15 00:05:58
【问题描述】:

如果发布请求通过 ajax 发送到特定的控制器功能,是否可以告诉 codeigniter 跳过会话超时重置。我在用户登录仪表板中有一个频繁的 ajax 调用来检查某些内容,但是这些调用使会话保持活动状态,因此即使用户保持非活动状态 10 分钟(sess_expiration 时间)会话也不会被杀死,并且他们仍然永远保持登录状态。

【问题讨论】:

  • 只有在您进行的 ajax 调用不需要会话信息(甚至不需要用户 ID)来运行时才有可能,但情况可能并非如此。如果是,您需要做的就是将 Ajax 调用定向到不加载会话库的隔离控制器

标签: php ajax codeigniter session


【解决方案1】:

如果(且仅当)您的 Ajax 调用完全与会话无关(也就是说,它不需要登录即可运行,它不需要来自用户的任何会话数据等),您可以提供服务来自单独的 ajax 特定控制器的 Ajax 请求,然后在使用该特定控制器时禁止会话库自动加载。

如果 ajax 调用需要登录用户,那你很不走运。

但是,如果您满足这些条件,请在 application/config/autoload.php 中找到 $autoload['libraries] 部分并使用这个肮脏的 hack:

// Here, an array with the libraries you want/need to be loaded on every controller
$autoload['libraries'] = array('form_validation');

// Dirty hack to avoid loading the session library on controllers that don't use session data and don't require the user to have an active session
$CI =& get_instance();
// uncomment the one that fits you better
// Alternative 1: you only have a single controller that doesn't need the session library
// if ($CI->router->fetch_class() != 'dmz') array_push($autoload['libraries'], 'session');
// END alternative 1

// Alternative 2: you have more than one controller that doesn't need the session library
// if (array_search($CI->router->fetch_class(), array('dmz', 'moredmz')) === false) array_push($autoload['libraries'], 'session');
// END alternative 2

在上面的代码中,dmzmoredmz 是我的两个假想的控制器名称,需要不加载会话库。只要不使用这些,session 库就会被推入自动加载并因此加载。否则,session 库将被忽略。

我实际上在我的一个站点上运行了此程序,以便允许来自我的负载均衡器的运行状况检查运行(在每个应用程序服务器上每 5 秒一次,来自主负载均衡器及其备份)并填满我的会话表包含无用的数据,并且像魅力一样工作。

不确定您使用的是哪个版本的 CI,但上述代码已在 CI 3.1.11 上测试。

现在,正如您所说的 Ajax 调用需要会话驱动程序,解决此问题的唯一方法是稍微弄乱会话驱动程序本身。在 3.1.11 中,会话驱动程序位于 system/libraries/Session/Session.php 中,您需要更改的部分是构造函数方法的最后部分(从第 160 行开始)。对于这个例子,我假设你的 Ajax 调用由一个名为“Ajax”的特定控制器处理

// This is from line 160 onwards
elseif (isset($_COOKIE[$this->_config['cookie_name']]) && $_COOKIE[$this->_config['cookie_name']] === session_id())
        {
            $CI =& get_instance();
            $new_validity = ($CI->router->fetch_class() !== 'ajax') ? time() + $this->_config['cookie_lifetime'] : $_SESSION['__ci_last_regenerate'] + $this->_config['cookie_lifetime'];

            setcookie(
                $this->_config['cookie_name'],
                session_id(),
                (empty($this->_config['cookie_lifetime']) ? 0 : $new_validity),
                $this->_config['cookie_path'],
                $this->_config['cookie_domain'],
                $this->_config['cookie_secure'],
                TRUE
            );
        }

        $this->_ci_init_vars();

        log_message('info', "Session: Class initialized using '".$this->_driver."' driver.");

简而言之,此示例(尚未对其进行测试,因此请在部署之前进行测试,可能有一两个错字)将首先实例化 CI 核心并从路由器获取控制器名称。如果它是常规控制器,它将确定新的 cookie 有效性为“现在加上配置中的 cookie 有效性”。如果是ajax控制器,cookie有效性将与当前有效性相同(上次重新生成时间加上cookie有效性..必须重申它,因为三元运算符需要它)

之后,setcookie 被修改为使用预先计算的 cookie 有效性,具体取决于 _config['cookie_lifetime'] 的值。

【讨论】:

  • 不幸的是,ajax 调用在用户登录时完成。有没有其他方法可以实现这一目标?我也尝试过使用 SSE,但它也可以让会话保持活跃!
  • 每当加载会话类时,会话有效性就会更新(可以说,它发生在自动驾驶仪上,并且没有直接的方法可以改变这种行为),所以没有。没有简单的解决方法。您需要摆弄 Session 类 (system/libraries/Session/Session.php) 并更改其构造函数以不重新验证 Ajax 请求的 cookie 有效性。不是很可取,但可能。在构造函数中查找setcookie 语句
  • 找到了这个,可能是要走的路:stackoverflow.com/questions/6759058/…
  • 这是一种丑陋的解决方法(另外,请记住,CakePHP 中的会话处理程序与 Codeigniter 的不同),但它是一条有点有趣的路径。我之前的评论指出了 Codeigniter 中 Session 类的类似内容。您可以使用 $CI =& get_instance(); 和 `if ($CI->router->fetch_class() != 'xhrcontroller')` 来确定会话是否需要再延长 10 分钟,并相应地更改 setcookie 调用.不是最干净的解决方案,但它会工作
  • 太棒了!我只是快速尝试对会话驱动程序进行一些更改(请参阅我的答案中的编辑)以防万一您可能需要它们
猜你喜欢
  • 2020-09-10
  • 1970-01-01
  • 2012-01-26
  • 2012-03-11
  • 2014-08-10
  • 2012-01-08
  • 2016-06-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多