会话表现出突然行为

10

我的 php 会话显示异常行为。情况如下:

  • 用户登录了应用程序(https://example.com)
  • 会话 cookie 有效期设置为7天。(从浏览器 cookie 生命周期验证)
  • 用户跳转到另一个域名(没有 https
  • 当用户尝试通过点击应用链接回来时,会话被销毁。
  • 这种行为是突然的。有时候,它仍然有效。

以下是我如何开始会话:

if(!$this->session_manager_issession_set()) {
            $this->set_ini_config();
            session_name($this->session_manager_name);
            session_set_cookie_params($this->session_cookie_life, "/"); //Required for browser cookie cleanup
}

session_start();

if(empty($_SESSION))
    {
        $output['status']   =   false;
    }
    else{
       // Fetch the variables
    }

public function session_manager_issession_set(){
        $output =   true;

        $session_status =   session_status();
        switch($session_status){
            case PHP_SESSION_ACTIVE :

            break;
            default:
                $output =   false;
        }

        return $output;
    }

private function set_ini_config(){
    $output =   true;

    ini_set('session.gc_probability', 1);   //If session expires then ensure that session is flushed and cleared at all instances
    ini_set('session.gc_divisor', 100);     //If session expires then ensure that session is flushed and cleared at all instances

    ini_set('session.gc_maxlifetime', 7*24*60*60);  //MAx life of session cookie
    ini_set('session.cookie_secure', true);

    return $output;
}

这可能是什么原因呢?我实现会话的方式有误吗?


尝试将 session_start(); 移动到文件顶部,在 <?php 之后。除此之外,也许你应该查看文档 - Fatal Error
当你说“用户移动到另一个域”时,这意味着不同的Web服务器,对吗? - Webomatik
@EagleEye,在调用session_start()之前需要先调用session_name()。 - Webomatik
@Webomatik 它在 session_start 之前被调用了!是的,它移动到了另一台 Web 服务器。 - user5735796
你确定用户回到了 https 而不是 http 吗? - Ramil Amerzyanov
显示剩余2条评论
5个回答

1
首先,你的函数session_manager_issession_set()基本上检查会话是否未启动(session_status() != PHP_SESSION_ACTIVE),但是然后你启动会话,忽略了会话可能已经在运行的事实。
如果会话名称对你很重要,那么你必须强制执行它:
if ($this->session_manager_issession_set()) {
    // session has already started, but we haven't set a name for it!
    throw new Exception("Session started prematurely");
}

// all fine, session isn't running; continue with setup
$this->set_ini_config();
session_name($this->session_manager_name);
session_set_cookie_params($this->session_cookie_life, "/");
// and finally start the session
session_start();

由于session.name设置了一个cookie的名称来存储会话ID,并且您使用了非默认名称,我的猜测是在您开始之前有一些东西启动了会话,因此您无法查看与幸运启动的会话相关联的数据。

另一个选项是保留所有代码,仅删除一行

session_name($this->session_manager_name); 

如果它有帮助的话,那么我一定是正确的。

1

在检查任何会话检查参数之前,从基础知识开始,例如简单地开始。

print_r($_SESSION);

这将简单地输出您在其中拥有的会话变量,这样您就可以看到服务器是否记住了会话及其变量。

接下来,我认为这里的一些答案是正确的,您要检查会话是否已启动,但您要检查的是会话是否仍然存在(不同的事情)...

因此,如果您知道会话变量中的某个键始终存在,则可以通过使用以下方式进行检查:

if(isset($_SESSION['your_key'])) {
// Your code if session has been made already
}

我知道这看起来很简单,但是在代码中回归基础并不一定是坏事,当你试图找出错误时 :) 所以尝试一下,如果上述两种方法都适用于您,则表示您正在使用一些错误的语句,即使您的会话变量完好无损也是错误的... :)

0

正如您在问题和评论中提到的那样,用户不仅要移动到不同的域,而且要完全移动到另一台服务器(因此从http更改为https对我们读者来说更有意义)。$_SESSION是一个保存在服务器上的超级全局变量,因此更改服务器是您的$_SESSION值被销毁的最可能原因。

事实上,它可能仍然存在,但由于您正在尝试从不同的服务器访问它,因此服务器找不到它,因此导致您(或服务器)认为它已被销毁(因为它仍然存储在启动会话的原始服务器上)。这就解释了为什么有时它可以工作,有时它不能工作,因为您可能在不同的服务器之间切换,并且有时您会幸运地在首次创建会话的同一台服务器上。


我不尝试从不同的服务器访问会话,而是从创建它的同一台服务器访问。用户移动到另一台服务器,当他回到同一台服务器时,会话得到验证。 - user5735796
@Karooka 你的意思是会话没有经过验证吗?因为如果它经过了验证,那么它应该是正常工作的,但事实并非如此,对吧? - Webeng
我所说的“已验证”是指检查$_SESSION是否包含会话变量。 - user5735796
@Karooka 我知道“验证”这个术语 :), 我想问的是你在之前那句话中的意思。在你的问题中,你说问题是验证,但现在你又说“用户移动到另一个服务器,当他回到同一个服务器时,会话已经验证”。所以在你的问题中,你说了一件事情,现在又说了相反的事情,所以我想问你的意思是什么,因为这两个陈述是相互矛盾的。 - Webeng

0
请阅读关于session.cookie_secure的内容,链接为php.net手册
这将把您的会话cookie绑定到仅安全(即https)连接。当从https切换到http时,会话丢失。

但是当回到 https 时,它不应该重新启动会话吗? - user5735796
是的,它应该这样 - 如果不是这种情况,那么可能有其他问题。但首先您应该检查session.cookie_secure设置。 - pocketrocket
如果您在具有相同域名的非 SSL vhost 中使用具有相同名称的新 cookie 覆盖它,则不会起作用。 - symcbean

0

Rafael说得对,你应该尝试使用更简单的代码基础来重新创建和解决问题。你还应该在代码中添加工具以查找浏览器返回了哪些cookies。

我实现session的方式有误吗?

是的。

这段代码难以阅读,不适当地使用了switch语句,没有充分的理由覆盖系统配置,还有许多其他奇怪的事情。最重要的是,这是一个非常不寻常的用例,你应该要求会话保持活动状态这么长时间(“记住我”功能与会话非常不同)。一旦你解决了会话持久性问题,你可能想阅读一些PHP样式标准并访问codereview.stackexchange.com。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接