title: PHP: Warning: session_regenerate_id(): Cannot regenerate session id - headers already sent
body: <p>Obviously I am not the only one experiencing this problem. However, I am unable to fix it based on other user postings I found related to this error-message.</p>
  
  <p>I get the following error:</p>
  
  <pre><code>( ! ) Warning: session_regenerate_id(): Cannot regenerate session id - headers already sent in C:\wamp\www\Creating-Secure-PHP-Websites\05_authentication\sample_app\private\functions\session_hijacking_functions.php on line 113
  Call Stack
  #   Time    Memory  Function    Location
  1   0.0000  244440  {main}( )   ..\login.php:0
  2   0.0830  322816  after_successful_login( )   ..\login.php:33
  3   0.0830  322864  session_regenerate_id ( )   ..\session_hijacking_functions.php:113
  
  ( ! ) Warning: Cannot modify header information - headers already sent by (output started at C:\wamp\www\Creating-Secure-PHP-Websites\05_authentication\sample_app\public\login.php:3) in C:\wamp\www\Creating-Secure-PHP-Websites\05_authentication\sample_app\private\functions\general_functions.php on line 7
  Call Stack
  #   Time    Memory  Function    Location
  1   0.0000  244440  {main}( )   ..\login.php:0
  2   0.0990  323120  redirect_to( )  ..\login.php:34
  3   0.0990  323256  header ( )  ..\general_functions.php:7
  </code></pre>
  
  <p>Login.php:</p>
  
  <pre><code>&lt;?php require_once("../private/initialize.php"); ?&gt;
  
  &lt;?php
  
  // Rather than require setting up a real database, 
  // we can fake one instead.
  initialize_fake_database();
  
  // initialize variables to default values
  $username = "";
  $password = "";
  $message = "";
  
  if(request_is_post() &amp;&amp; request_is_same_domain()) {
  
    if(!csrf_token_is_valid() || !csrf_token_is_recent()) {
      $message = "Sorry, request was not valid.";
    } else {
      // CSRF tests passed--form was created by us recently.
  
          // retrieve the values submitted via the form
      $username = $_POST['username'];
      $password = $_POST['password'];
  
          if(has_presence($username) &amp;&amp; has_presence($password)) {
  
              // Search our fake database to retrieve the user data
              $sqlsafe_username = sql_prep($username);
              $user = find_one_in_fake_db('users', 'username', $sqlsafe_username);
  
          if($user &amp;&amp; password_verify($password, $user['hashed_password'])) {
              // successful login
            after_successful_login();
            redirect_to('private.php');
          } else {
            // failed login
            $message = "Username/password combination not found.";
          }
  
          } else {
              // username or password left blank, just re-display the form.
          }
    }
  }
  
  ?&gt;
  
  &lt;!doctype html&gt;
  &lt;html lang="en"&gt;
    &lt;head&gt;
      &lt;meta charset="utf-8"&gt;
      &lt;title&gt;Log in&lt;/title&gt;
    &lt;/head&gt;
    &lt;body&gt;
  
      &lt;?php
        if($message != "") {
          echo '&lt;p&gt;' . h($message) . '&lt;/p&gt;';
        }
      ?&gt;
  
      &lt;p&gt;Please log in.&lt;/p&gt;
  
      &lt;form action="login.php" method="POST" accept-charset="utf-8"&gt;
        &lt;?php echo csrf_token_tag(); ?&gt;
        Username: &lt;input type="text" name="username" value="&lt;?php echo h($username); ?&gt;" /&gt;&lt;br /&gt;
              &lt;br /&gt;
        Password: &lt;input type="password" name="password" value="" /&gt;&lt;br /&gt;
              &lt;br /&gt;
        &lt;input type="submit" name="submit" value="Log in" /&gt;
      &lt;/form&gt;
  
  &lt;?php
  // Uncomment if you want to examine the contents of the fake database
  // echo "&lt;br /&gt;&lt;br /&gt;";
  // echo "--- fake database contents ---";
  // var_dump($_SESSION['fake_database']);
  // echo "------------------------------";
  ?&gt;
    &lt;/body&gt;
  &lt;/html&gt;
  </code></pre>
  
  <p>general_functions.php:</p>
  
  <pre><code>&lt;?php
  // Put all of your general functions in this file
  
  // header redirection often requires output buffering 
  // to be turned on in php.ini.
  function redirect_to($new_location) {
    header("Location: " . $new_location);
    exit;
  }
  
  ?&gt;
  </code></pre>
  
  <p>session_hijacking.php:</p>
  
  <pre><code>&lt;?php
  // Useful php.ini file settings:
  // session.cookie_lifetime = 0
  // session.cookie_secure = 1
  // session.cookie_httponly = 1
  // session.use_only_cookies = 1
  // session.entropy_file = "/dev/urandom"
  
  // Must have already called:
  // session_start();
  
  // Function to forcibly end the session
  function end_session() {
      // Use both for compatibility with all browsers
      // and all versions of PHP.
      session_unset();
    session_destroy();
  }
  
  // Does the request IP match the stored value?
  function request_ip_matches_session() {
      // return false if either value is not set
      if(!isset($_SESSION['ip']) || !isset($_SERVER['REMOTE_ADDR'])) {
          return false;
      }
      if($_SESSION['ip'] === $_SERVER['REMOTE_ADDR']) {
          return true;
      } else {
          return false;
      }
  }
  
  // Does the request user agent match the stored value?
  function request_user_agent_matches_session() {
      // return false if either value is not set
      if(!isset($_SESSION['user_agent']) || !isset($_SERVER['HTTP_USER_AGENT'])) {
          return false;
      }
      if($_SESSION['user_agent'] === $_SERVER['HTTP_USER_AGENT']) {
          return true;
      } else {
          return false;
      }
  }
  
  // Has too much time passed since the last login?
  function last_login_is_recent() {
      $max_elapsed = 60 * 60 * 24; // 1 day
      // return false if value is not set
      if(!isset($_SESSION['last_login'])) {
          return false;
      }
      if(($_SESSION['last_login'] + $max_elapsed) &gt;= time()) {
          return true;
      } else {
          return false;
      }
  }
  
  // Should the session be considered valid?
  function is_session_valid() {
      $check_ip = true;
      $check_user_agent = true;
      $check_last_login = true;
  
      if($check_ip &amp;&amp; !request_ip_matches_session()) {
          return false;
      }
      if($check_user_agent &amp;&amp; !request_user_agent_matches_session()) {
          return false;
      }
      if($check_last_login &amp;&amp; !last_login_is_recent()) {
          return false;
      }
      return true;
  }
  
  // If session is not valid, end and redirect to login page.
  function confirm_session_is_valid() {
      if(!is_session_valid()) {
          end_session();
          // Note that header redirection requires output buffering 
          // to be turned on or requires nothing has been output 
          // (not even whitespace).
          header("Location: login.php");
          exit;
      }
  }
  
  
  // Is user logged in already?
  function is_logged_in() {
      return (isset($_SESSION['logged_in']) &amp;&amp; $_SESSION['logged_in']);
  }
  
  // If user is not logged in, end and redirect to login page.
  function confirm_user_logged_in() {
      if(!is_logged_in()) {
          end_session();
          // Note that header redirection requires output buffering 
          // to be turned on or requires nothing has been output 
          // (not even whitespace).
          header("Location: login.php");
          exit;
      }
  }
  
  
  // Actions to preform after every successful login
  function after_successful_login() {
      // Regenerate session ID to invalidate the old one.
      // Super important to prevent session hijacking/fixation.
      session_regenerate_id();
  
      $_SESSION['logged_in'] = true;
  
      // Save these values in the session, even when checks aren't enabled 
    $_SESSION['ip'] = $_SERVER['REMOTE_ADDR'];
    $_SESSION['user_agent'] = $_SERVER['HTTP_USER_AGENT'];
      $_SESSION['last_login'] = time();
  
  }
  
  // Actions to preform after every successful logout
  function after_successful_logout() {
      $_SESSION['logged_in'] = false;
      end_session();
  }
  
  // Actions to preform before giving access to any 
  // access-restricted page.
  function before_every_protected_page() {
      confirm_user_logged_in();
      confirm_session_is_valid();
  }
  
  
  // Uncomment to demonstrate usage
  
  // if(isset($_GET['action'])) {
  //  if($_GET['action'] == "login") {
  //      after_successful_login();
  //  }
  //  if($_GET['action'] == "logout") {
  //      after_successful_logout();
  //  }
  // } 
  // 
  // echo "Session ID: " . session_id() . "&lt;br /&gt;";
  // echo "Logged in: " . (is_logged_in() ? 'true' : 'false') . "&lt;br /&gt;";
  // echo "Session valid: " . (is_session_valid() ? 'true' : 'false') . "&lt;br /&gt;";
  // echo "&lt;br /&gt;";
  // echo "--- SESSION ---&lt;br /&gt;";
  // var_dump($_SESSION);
  // echo "--------------------&lt;br /&gt;";
  // echo "&lt;br /&gt;";
  // 
  // echo "&lt;a href=\"?action=new_page\"&gt;Simulate a new page request&lt;/a&gt;&lt;br /&gt;";
  // echo "&lt;a href=\"?action=login\"&gt;Simulate a log in&lt;/a&gt;&lt;br /&gt;";
  // echo "&lt;a href=\"?action=logout\"&gt;Simulate a log out&lt;/a&gt;";
  
  ?&gt;
  </code></pre>