【问题标题】:Error — session_destroy() — Trying to destroy uninitialized session错误 — session_destroy() — 试图销毁未初始化的会话
【发布时间】:2013-08-31 17:41:45
【问题描述】:

我在 PHP 代码中使用 session_destroy() 时遇到错误。

以下脚本在每个页面上,如果用户登录,它会检查会话是否有效,如果不是则终止会话。

session_start();

// check for users already signed in and check session
if (isset($_SESSION['user_id'])) {
    $uid = $_SESSION['user_id'];

    // check user_id is a valid id
    if (!is_numeric($uid) || $uid < 0) {
        session_unset();
        session_destroy();
        session_regenerate_id(true);
    }

    // if user agent is different, kill session
    if ($_SESSION['user_agent'] != $_SERVER['HTTP_USER_AGENT']) {
        session_unset();
        session_destroy();
        session_regenerate_id(true);
    }

    // if user's last login record fails to match session_id, kill session
    $SQL = "SELECT user_session FROM users_logins ";
    $SQL .= "WHERE user_id = :user_id ";
    $SQL .= "ORDER BY time_in DESC LIMIT 1;";
    $STH = $DBH_P->prepare($SQL);
    $STH->bindParam(':user_id', $uid);
    $STH->execute();
    $row = $STH->fetch();
    if ($STH->rowCount() > 0) {
        $db_sid = $row['user_session'];
    }
    if ($db_sid !== session_id()) {
        session_unset();
        session_destroy();
        session_regenerate_id(true);
    }
}

我收到的错误表明失败来自上一次session_destroy() 调用。

我是否正确使用session_destroy()?我在这里阅读了其他问题,但大多数答案建议必须在销毁它之前使用session_start(),但我已经在检查开始之前在顶部开始了会话。

【问题讨论】:

  • 为什么你使用 session_unset 和 session_destroy?重新生成 id 就足够了。为什么要检查会话中的用户 ID 是否为数字?如果这应该是必要的——在你把它放到会话之前做。
  • @CBroe 如果发现任何问题,我正在使用 session_unset 和 session_destroy 将用户注销,因此当他们访问另一个页面时,他们必须再次登录。由于会话劫持,我正在检查 user_id 是否为数字。仅仅因为我在将它放入会话之前检查了它,并不意味着如果有人玩过它,它就会在此页面上有效。
  • 我现在在 SO 上追踪 session_unset 的神话,因为它是从昨天开始的。不管你告诉用户什么,总有谣言说你认为适合放入脚本的功能越多越好。其实恰恰相反。
  • 您验证/过滤会话值是好的顺便说一句,将会话数据视为注入到您的脚本中的用户数据,因为当您正确写入时,它实际上是。顺便说一句,这同样适用于从您的数据库返回的数据。

标签: php session


【解决方案1】:

您在那里做了一些疯狂的事情(但您需要与自己协商,我的答案中没有涉及),您看到错误消息的原因很简单:

 session_regenerate_id(true);

正在命令 PHP 销毁旧会话。问题是,你已经这样做了,前一行:

 session_destroy();
 session_regenerate_id(true);

所以从上面看一下。没有理由以强迫症的方式将您认为合适的功能(但实际上并不了解/不太了解)扔到您的会话处理中。相反,如果您想在其中放置一些安全网,请使用旨在完成这项工作的一个函数并实际处理它的返回值。那会更有帮助。

【讨论】:

  • 非常感谢您的解释。我想我对检查我的会话有点忘乎所以。不久前,我来自 Classic ASP,管理会话有点简单(出于某种原因,因为它很垃圾)。如果任何条件为真,也许我会使用session_regenerate_id(true);,将用户重定向到所有会话数据都会被清除的注销页面,然后将它们弹回他们所在的页面。
  • 是的,这就是我想说的,只有这个函数才能做到(以true为参数)。
猜你喜欢
  • 2013-08-13
  • 1970-01-01
  • 1970-01-01
  • 2014-02-23
  • 2023-03-19
  • 1970-01-01
  • 1970-01-01
  • 2012-04-15
  • 2013-06-26
相关资源
最近更新 更多