PHP Session认为除非执行回声,否则它将被劫持

时间:2013-09-05 16:56:02

标签: php session

我正在编写一个简单的网站,允许用户登录,填写提交到数据库然后注销的表单。为了管理会话,我使用了TreeHouse在下一页描述的会话管理器:http://blog.teamtreehouse.com/how-to-create-bulletproof-sessions

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

实现似乎在我的本地计算机上没有任何问题,但是当我将其上传到服务器时,每次刷新都会导致preventHijacking()函数返回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;
  }
}
?>

1 个答案:

答案 0 :(得分:0)

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

在返回之前尝试将ob_end_flush();放在那里。这可能会解决它。