在 PHP 中销毁会话时出错

Posted

技术标签:

【中文标题】在 PHP 中销毁会话时出错【英文标题】:Error while destroying session in PHP 【发布时间】:2011-09-26 18:56:35 【问题描述】:

我在 php(版本 5.2.10)的会话处理中遇到问题。我正在使用下面提到的功能进行登录、注销和验证会话。

登录() session_set_cookie_params(0); session_start(); session_regenerate_id(true); $_SESSION['user_id'] 验证会话() session_set_cookie_params(0); session_start(); if (isset($_SESSION['user_id']) === FALSE) session_destroy(); 登出(); header("位置:登录页面"); 登出() session_set_cookie_params(0); session_start(); $_SESSION = 数组(); setcookie(session_name(), '', time() - 3600, '/'); session_destroy();

每个页面首先调用 validate_session() 函数。如果会话无效,它将重定向到登录页面。 login() 函数用于为用户创建会话。 当用户点击注销时,会调用 logout() 函数来销毁会话。

问题是:logout() 函数随机抛出警告:Warning: session_destroy(): Session object destroy failed

我很少收到此警告。就像在 20-30 次注销电话中一样,我得到了一次。有什么想法吗?

我在 windows xp 机器上开发。

更新:会话存储在文件系统中。 路径:C:\WINDOWS\Temp

【问题讨论】:

看来你已经很久没有在***上接受任何答案了... 是的!我在***中不是很活跃。在某些情况下,我还没有得到满意的答案。 嗨 Varun,您能解释一下为什么在比较中使用trip equals吗?通常 if(!isset()) 就足够了,我知道它更铁定但 isset() 应该只返回一个布尔值,你真的需要验证它的类型吗?这可能不太可能,但也许偶尔会在不应该的时候返回 true? 建议将debug_print_backtrace() 添加到注销功能,并跟踪输出然后比较输出,如果有差异,可能是不同的调用路径产生了错误。 (见php.net/manual/en/function.debug-print-backtrace.php) 感谢大家的建议。我无法重现此内容(我使用与之前相同的代码)。事实上,我很久没看到这个错误了。现在我不知道是什么原因造成的。 【参考方案1】:

您如何存储会话?如果是基于文件的,可能是超时或权限错误?

另外,我想知道 regenerate_id 是否会导致销毁函数查找技术上不再存在的会话。您是否尝试在 regenerate 函数中将该布尔参数设置为 false ?

我们在一个 CakePHP 应用程序上遇到了这个问题,但我们通过调整 Cake 设置来纠正它。

【讨论】:

会话存储在文件系统中。我也尝试了你的建议,但仍然有一次这个错误。正如我所提到的,错误很少发生(有时一天一次),我很难做出一些改变然后看看它是否解决了问题。 另一个问题,当警告出现时,用户真的退出了吗?或者更重要的是,除了警告之外,其他一切正常吗?如果是这样,您可能会考虑抑制警告,直到您弄清楚 - 也就是说,如果这是一个生产环境。【参考方案2】:

找到something,这可能对这个主题有用。基本问题是:

    会话开始时是否有效 -- session_start() 的返回值是多少? 会话文件是否存在于 PHP.ini session.save_path 中并且可以删除。

我怀疑你的情况是第一个。我不记得在哪里,但我想我见过会话自身失效然后出于某种原因尝试重复该过程的情况。

【讨论】:

【参考方案3】:

是否在 validate_session() 之外的其他地方调用了 logout() ?如果没有,问题可能是在 logout() 之前调用 session_destroy()

你可以试试这个:

validate_session()

    session_set_cookie_params(0);
    session_start();
    if ( !isset( $_SESSION['user_id'] ) ) 
        logout();
        header("Location: login_page");
    


logout()

    $_SESSION = array();
    setcookie(session_name(), '', time() - 3600, '/');
    session_destroy();

【讨论】:

这也是我的首选解决方案,将 session_destroy 添加到注销函数而不是 validate_session() 函数是合乎逻辑的。此解决方案提供的优势之一是防止在注销页面上创建新会话,这将消除复制 session_destroy() 函数的需要。

以上是关于在 PHP 中销毁会话时出错的主要内容,如果未能解决你的问题,请参考以下文章

远程销毁 php 中的会话(用户在其他地方登录)?

如何正确启动和销毁会话?

单击链接时销毁 PHP 会话

PHP session_destroy()警告会话对象销毁失败[重复]

如何一键销毁php会话

当用户关闭浏览器而不单击注销时销毁或取消设置会话[重复]