0

我正在编写一个简单的网站,允许用户登录,填写提交到数据库的表单,然后注销。为了管理会话,我使用了 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;
  }
}
?>
4

1 回答 1

0

I could be way out here (it's been a while) but that sounds like the buffer containing the headers isn't being flushed for some reason. Providing body would force them to be flushed, so maybe not providing the body doesn't flush?

Try putting ob_end_flush(); in there before you return. That may fix it.

于 2013-09-05T17:22:35.240 回答