PHP Session相信它';除非执行回音,否则它将被劫持

PHP Session相信它';除非执行回音,否则它将被劫持,php,session,Php,Session,我正在写一个简单的网站,允许用户登录,填写一张表格,然后提交到数据库,然后注销。为了管理会话,我使用了会话管理器,该管理器由TreeHouse在下一页中描述: 为了防止劫持,客户端的IP地址和用户代理存储在会话变量中,并与每个页面上这些属性的服务器值进行比较。如果它们不匹配,则假定会话已被劫持并重置 该实现似乎在我的本地计算机上运行,没有任何问题,但当我将其上载到服务器时,每次页面刷新都会导致preventjacking()函数返回false(表示它认为会话已被劫持)。但是,如果我在该函数中回显

我正在写一个简单的网站,允许用户登录,填写一张表格,然后提交到数据库,然后注销。为了管理会话,我使用了会话管理器,该管理器由TreeHouse在下一页中描述:

为了防止劫持,客户端的IP地址和用户代理存储在会话变量中,并与每个页面上这些属性的服务器值进行比较。如果它们不匹配,则假定会话已被劫持并重置

该实现似乎在我的本地计算机上运行,没有任何问题,但当我将其上载到服务器时,每次页面刷新都会导致preventjacking()函数返回false(表示它认为会话已被劫持)。但是,如果我在该函数中回显任何文本,问题就会神秘地消失,整个过程按照我的预期进行(除了现在显示在我的表单:P上方的回显文本位)

我不知道为什么会出现这种情况,也不知道如何解决。会话管理器代码如下所示。在每个页面的开头,我使用它来启动会话,然后每个页面只使用或设置它需要的任何变量。如果有人能提出为什么函数总是返回false,除非它回显文本,或者建议我需要做什么修改,以便它以预期的方式运行,我将非常感激

<?php
class SessionManager {

  protected static $timeout = 600; // Time before automatic logout for the session

  static function sessionStart($name, $limit=0, $path='/', $domain=null, $secure=null) {
    // Set the cookie name before we start
    session_name($name.'_Session');

    // Set the domain to default to the current domain
    $domain = isset($domain)? $domain : $_SERVER['SERVER_NAME'];

    // Set the default secure value to whether the site is being accessed with SSL
    $https = isset($secure)? $secure : isset($_SERVER['HTTPS']);

    // Set the cookie settings and start the session
    session_set_cookie_params($limit, $path, $domain, $secure, True);
    session_start();

    // Make sure the session hasn't expired and destroy it if it has
    if(self::validateSession()) {

      // Check to see if the session is new or a hijacking attempt     
      if(!self::preventHijacking()) {      
        // Reset session data and regenerate ID
        $_SESSION=array();
        $_SESSION['IPaddress'] = $_SERVER['REMOTE_ADDR'];
        $_SESSION['userAgent'] = $_SERVER['HTTP_USER_AGENT'];
        self::regenerateSession();

        // Give a 5% chance of the session ID changing on any request
      } else if (rand(1, 100) <= 5) {
        self::regenerateSession();
      }

      $_SESSION['LAST_ACTIVITY'] = time();
    } else {
      $_SESSION = array();
      session_destroy();
      session_start();
    }
  }

  static function preventHijacking() {
    if(!isset($_SESSION['IPaddress']) || !isset($_SESSION['userAgent'])) {
      return false;
    }

    if($_SESSION['IPaddress'] != $_SERVER['REMOTE_ADDR']) {
      return false;
    }

    if($_SESSION['userAgent'] != $_SERVER['HTTP_USER_AGENT']) {
      return false;
    }

    return true;
  }

  static function regenerateSession() {

    // If this session is obsolete, it means that there already is a new id
    if(isset($_SESSION['OBSOLETE']) && $_SESSION['OBSOLETE'] === True) {
      return;
    }

    // Set current session to expire in 10 seconds
    $_SESSION['OBSOLETE'] = True;
    $_SESSION['EXPIRES'] = time() + 10;

    // Create new session without destroying the old one
    session_regenerate_id(false);

    // Grab current session ID and close both sessions to allow other scripts to use them
    $newSession = session_id();
    session_write_close();

    // Set session ID to the new one and start it back up again
    session_id($newSession);
    session_start();

    // Now we unset the obsolete and expiration values for the session we want to keep
    unset($_SESSION['OBSOLETE']);
    unset($_SESSION['EXPIRES']);
  }

  static protected function validateSession() {
    // Check if something went wrong
    if(isset($_SESSION['OBSOLETE']) && !isset($_SESSION['EXPIRES'])) {
      return false;
    }

    // Test if this is an old session which has expired
    if(isset($_SESSION['EXPIRES']) && $_SESSION['EXPIRES'] < time()) {
      return false;
    }

    // Check if the user's login has timed out
    if(isset($_SESSION['LAST_ACTIVITY']) && (time() - $_SESSION['LAST_ACTIVITY']) > self::$timeout) {
      return false;
    }

    return true;
  }
}
?>

我可能已经离开这里了(已经有一段时间了),但这听起来像是由于某种原因没有刷新包含标题的缓冲区。提供身体会迫使它们被冲洗,所以不提供身体可能不会冲洗


尝试放置
ob_end_flush()在你回来之前在那里。这可能会解决问题。

您的浏览器是否正在缓存页面?如果是这样,请尝试在HTML标题块之后添加这两个标记。你有没有发现是什么导致了这个问题。我遇到了完全相同的问题,我不能添加任何新的会话变量,除非它认为它被劫持了