0

I have created a recursive document, which basically acts as two different pages (first enter ID and then enter password), in order to protect or better hide the URL of the ultimate destination.

After having implemented a function to prevent multiple active sessions for the same user I began receiving warnings, which can be seen in the image below, before the page redirects. I know what the warnings mean and why they're caused. The warnings are a result of session_start() and session_regenerate_id() on lines 40, 41, 80, and 81.

enter image description here

Strangely, however, if I don't include session_start() and session_regenerate_id() the page never redirects or rather redirects to itself again since $_SESSION["session"] never ends up being set.

All of this is due to the way I'm destroying any additional session(s). I found the method here. I'm not even sure if this is the correct way to terminate a particular session, but it seems to work (although it's ultimately responsible for the logic which causes warnings).

I'm wondering how I can avoid or address these warnings while achieving the same end result but without splitting the logic into multiple pages??

Any insights would be appreciated.

Below is the actual code.

<?php
  session_start();
  // isset($_SESSION["session"]) && !empty($_SESSION["session"])
  if ($_SESSION["session"]) {
    echo "<script type='text/javascript'> location.href = 'showcase.php' </script>";
  }

  if ($_SERVER["REQUEST_METHOD"] === "POST") {
    // enter password or set password
    if (isset($_POST["password"]) && empty($_POST["password"])) {
      $error    = "A password is required.";
      $identity = "password";
      $tip      = "Password";
      $prompt   = "Enter Password";
    } else if (isset($_POST["password"]) && !empty($_POST["password"])) {
      include "inc/dat/connect.php";
      if ($_SESSION["promptPersist"] === "Enter Password") {
        // compare password
        $sql    = "SELECT prim, pass, sess FROM users WHERE usrn = :id";
        $stmt   = $conn->prepare($sql);
        $stmt->bindParam(":id", $_SESSION["idPersist"]);
        $stmt->execute();
        $result = $stmt->fetch(PDO::FETCH_ASSOC);
        if (password_verify($_POST["password"], $result["pass"])) {
          unset($_SESSION["promptPersist"]);
          $idPersist = $_SESSION["idPersist"];

          // deactivate any other session of same user
          $sql  = "SELECT sess FROM users WHERE usrn = :id";
          $stmt = $conn->prepare($sql);
          $stmt->bindParam(":id", $_SESSION["idPersist"]);
          $stmt->execute();
          $result = $stmt->fetch(PDO::FETCH_ASSOC);
          session_id($result["sess"]);
          session_start();
          session_unset();
          session_destroy();

          // start new session; set pass and sess
          session_start();
          session_regenerate_id(); // for safe keeping
          $_SESSION["idPersist"] = $idPersist;
          unset($idPersist);
          $sql  = "UPDATE users SET sess = :session WHERE usrn = :id";
          $stmt = $conn->prepare($sql);
          $stmt->bindParam(":id", $_SESSION["idPersist"]);
          $stmt->bindParam(":session", session_id());
          $stmt->execute();

          // set session variable to establish persistent session
          $sql  = "SELECT prim FROM users WHERE usrn = :id";
          $stmt = $conn->prepare($sql);
          $stmt->bindParam(":id", $_SESSION["idPersist"]);
          $stmt->execute();
          $result = $stmt->fetch(PDO::FETCH_ASSOC);
          $_SESSION["session"] = $result["prim"];
          echo "<script type='text/javascript'> location.href = 'showcase.php' </script>";
        } else {
          $error    = "Password is incorrect.";
          $identity = "password";
          $tip      = "Password";
          $prompt   = "Enter Password";
        }
      } else if ($_SESSION["promptPersist"] === "Set Password") {
        unset($_SESSION["promptPersist"]);
        $idPersist = $_SESSION["idPersist"];

        // deactivate any other session of same user
        $sql  = "SELECT sess FROM users WHERE usrn = :id";
        $stmt = $conn->prepare($sql);
        $stmt->bindParam(":id", $_SESSION["idPersist"]);
        $stmt->execute();
        $result = $stmt->fetch(PDO::FETCH_ASSOC);
        session_id($result["sess"]);
        session_start();
        session_unset();
        session_destroy();

        // start new session; set pass and sess
        session_start();
        session_regenerate_id(); // for safe keeping
        $_SESSION["idPersist"] = $idPersist;
        unset($idPersist);
        $sql  = "UPDATE users SET pass = :password, sess = :session WHERE usrn = :id";
        $stmt = $conn->prepare($sql);
        $stmt->bindParam(":id", $_SESSION["idPersist"]);
        $stmt->bindParam(":password", password_hash($_POST["password"], PASSWORD_DEFAULT));
        $stmt->bindParam(":session", session_id());
        $stmt->execute();

        // set session variable to establish persistent session
        $sql  = "SELECT prim FROM users WHERE usrn = :id";
        $stmt = $conn->prepare($sql);
        $stmt->bindParam(":id", $_SESSION["idPersist"]);
        $stmt->execute();
        $result = $stmt->fetch(PDO::FETCH_ASSOC);
        $_SESSION["session"] = $result["prim"];
        echo "<script type='text/javascript'> location.href = 'showcase.php' </script>";
      }
      $conn = null;
    }

    // enter id
    if (!isset($_POST["password"]) && empty($_POST["id"])) {
      $error  = "An ID is required.";
    } else if (!isset($_POST["password"]) && !empty($_POST["id"])) {
      include "inc/dat/connect.php";
      $id     = trim($_POST["id"]);
      $id     = stripslashes($_POST["id"]);
      $id     = htmlspecialchars($_POST["id"]);
      $sql    = "SELECT usrn, pass FROM users WHERE usrn = :id";
      $stmt   = $conn->prepare($sql);
      $stmt->bindParam(":id", $id);
      $stmt->execute();
      $result = $stmt->fetch(PDO::FETCH_ASSOC);
      if ($result) {
        $error                 = "";
        $identity              = "password";
        $tip                   = "Password";
        $_SESSION["idPersist"] = $id;
        if (is_null($result["pass"])) {
          $prompt                    = "Set Password";
          $_SESSION["promptPersist"] = "Set Password";
        } else {
          $prompt                    = "Enter Password";
          $_SESSION["promptPersist"] = "Enter Password";
        }
      } else {
        $error = strtoupper($_POST["id"])." does not exist.";
      }
      $conn = null;
    }
  }
?>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">

<html>
  <head>
    <link href="css/index.css" rel="stylesheet">
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
    <title>joli</title>
  </head>
  <body>
    <form
    accept-charset ="UTF-8"
    action         ="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]); ?>"
    enctype        ="application/x-www-form-urlencoded"
    method         ="post">
      <div id="error">
        <?php echo $error; ?>
      </div>
      <div class="strict">
        <input
        id    ="<?php echo (empty($identity)) ? "id" : $identity; ?>"
        name  ="<?php echo (empty($identity)) ? "id" : $identity; ?>"
        size  ="25"
        title ="<?php echo (empty($tip)) ? "ID" : $tip; ?>"
        type  ="text"
        >
        <input
        id    ="submit"
        name  ="submit"
        type  ="submit"
        value ="<?php echo (empty($prompt)) ? "Enter ID" : $prompt; ?>"
        >
      </div>
    </form>
    <script type="text/javascript" src="jas/index.js"></script>
  </body>
</html>
oldboy
  • 5,729
  • 6
  • 38
  • 86
  • `session_start(); session_unset(); session_destroy();` ??? `unset($_SESSION['session'])` ? Redirects should be done like `header('LOCATION:showcase.php'); die;`. Just a comment. – StackSlave Aug 24 '17 at 01:11
  • @PHPglue that's precisely what i'm doing. `session_id(oldsessionid); session_start(); session_unset(); session_destroy()` :/ – oldboy Aug 24 '17 at 01:13
  • Find the code that prints `Connected successfully`. You need to call the session functions before you do that. – Barmar Aug 24 '17 at 01:14
  • You should not use `session_start()` twice, and not after headers are sent. – StackSlave Aug 24 '17 at 01:15
  • @Barmar if you bothered to read, let alone understand my post/question, you would realize that it's not a duplicate of that other question. i KNOW why it's happening. the question asks **"how to deal with it WITHOUT breaking the logic into multiple pages since that logic is NECESSARY for the site to function properly"** – oldboy Aug 24 '17 at 01:17
  • @Barmar that is my database connection script. i have to connect to the database prior to that in order to retrieve the old session id which i end up destroying – oldboy Aug 24 '17 at 01:18
  • Why do you think you have to break it into multiple pages? You can either reorder the code, or you can use the output buffering functions. – Barmar Aug 24 '17 at 01:18
  • 1
    The database connection script shouldn't print anything. – Barmar Aug 24 '17 at 01:19
  • Let's face it... this code is just bad practice. – StackSlave Aug 24 '17 at 01:19
  • @Barmar i highly doubt there is any way to reorder the code so that the logic works without it becoming more repetitive than it already is. i have no idea what output buffering functions are. i'm new to php and sql – oldboy Aug 24 '17 at 01:20
  • @PHPglue i'm sure it is but i could care less about best practices with this project – oldboy Aug 24 '17 at 01:20
  • @Anthony The answers in the question I linked to explain how to use the output buffering functions to work around this. – Barmar Aug 24 '17 at 01:21
  • @Barmar no need. i was using the echoing for testing, but magically by removing the echos in the database connection script resolved the issue. great suggestion!! thx for the help <3 – oldboy Aug 24 '17 at 01:24
  • @Barmar post that as the solution and i'll accept it – oldboy Aug 24 '17 at 01:26
  • Can't post an answer to a closed question. The duplicate question explains everything anyone needs to know about this error. – Barmar Aug 24 '17 at 01:28
  • @Barmar alrighty then – oldboy Aug 24 '17 at 01:44

0 Answers0