【问题标题】:Session showing abrupt behavior会话显示突然行为
【发布时间】:2016-09-01 13:50:04
【问题描述】:

我的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 之后。除此之外,也许你应该看看documentation
  • 当您说“用户移动到另一个域”时,这意味着不同的 Web 服务器,对吧?
  • @EagleEye, session_name() 需要在 session_start() 之前调用
  • @Webomatik 它在 session_start 之前被调用!是的,它移动到不同的网络服务器
  • @Webomatik 它有时也有效,$_SESSION 是空的

标签: php session cookies logout


【解决方案1】:

Rafael 说您应该尝试使用更简单的代码库重新创建和解决问题是正确的。您还应该检测您的代码以找出浏览器返回的 cookie

我是否以不正确的方式实施会话?

是的。

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

【讨论】:

    【解决方案2】:

    在检查任何 Session 检查参数之前, 从基础开始,例如简单地开始

    print_r($_SESSION);
    

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

    接下来,我认为这里的一些答案是关于某事的, 你检查你的会话是否已经开始,但你想检查一个会话是否仍然存在(不是同一件事)......

    因此,如果您知道会话变量中的某个键将始终存在,那么只需使用以下命令进行检查:

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

    我知道这看起来很简单,但是当你试图找出你的错误时,回到代码中的基础并不是一件坏事 :) 所以试试这个,如果上述两种方法都对你有用,那么即使你的 Session 变量是完整的,你也使用了一些错误的陈述,这些陈述是错误的...... :)

    【讨论】:

      【解决方案3】:

      首先,您的函数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); 
      

      如果有帮助,那我一定是对的。

      【讨论】:

        【解决方案4】:

        请阅读session.cookie_securephp.net manual

        这会将您的会话 cookie 绑定到仅安全(即 https)连接。从https切换到http导致会话丢失

        【讨论】:

        • 但是当回到https时不应该重新启动会话吗?
        • 是的,它应该 - 如果不是这样的话,还有其他事情发生在上面。但首先你应该检查session.cookie_secure 设置。
        • 如果您在非 SSL 虚拟主机中使用具有相同名称的新 cookie 覆盖它,则不会具有相同的域名
        【解决方案5】:

        正如您在问题和 cmets 中提到的,用户不仅移动到不同的域,而且完全移动到不同的服务器(因此从 httphttps 的更改对我们读者来说更有意义) . $_SESSION 是保存在服务器上的超全局变量,因此更改服务器是您的 $_SESSION 值被破坏的最可能原因。

        事实上,它可能仍然存在,但是由于您尝试从其他服务器访问它,因此服务器找不到它,因此导致您(或服务器)相信它被销毁(因为它位于启动会话的原始服务器上)。这可以解释为什么它有时有效,有时无效,因为您可能在服务器之间切换,有时您很幸运,并且位于最初创建会话的同一台服务器上。

        【讨论】:

        • 我不会尝试从其他服务器访问会话,而是从创建会话的同一服务器访问。用户移动到不同的服务器,当他回到同一个服务器时,会话得到验证。
        • @Karooka 你的意思是会话没有经过验证?因为如果它经过验证,那么它会正常工作,但它不是,对吗?
        • 通过验证我的意思是说,检查$_SESSION 是否包含会话变量。
        • @Karooka 我知道验证这个词:),我要问的是你在上一句中的意思。在您的问题中,您说问题正在验证,但现在您说“用户移动到另一台服务器,当他回到同一台服务器时,会话已验证”。所以在你的问题中你说的是一件事,现在你说的是相反的,所以我问你是什么意思,因为这两个陈述相互矛盾。
        猜你喜欢
        • 2011-10-05
        • 1970-01-01
        • 2014-07-02
        • 1970-01-01
        • 1970-01-01
        • 2010-12-22
        • 2018-09-16
        • 2018-06-22
        • 2019-10-25
        相关资源
        最近更新 更多