Comprobando si el usuario ya inició sesión, verificación de cookies

Tengo un problema con algo que ya publiqué, pero pensé en volver a preguntar el problema porque ahora tengo más código.

El código ORIGINAL que he usado para el tutorial

function checkLoggedIn($page)
{
   $loginDiv = '';
   $action = '';
   if (isset($_POST['action']))
   {
      $action = stripslashes ($_POST['action']);
   }

   session_start ();

   // Check if we're already logged in, and check session information against cookies
   // credentials to protect against session hijacking
   if (isset ($_COOKIE['project-name']['userID']) &&
       crypt($_SERVER['REMOTE_ADDR'] . $_SERVER['HTTP_USER_AGENT'],
             $_COOKIE['project-name']['secondDigest']) ==
       $_COOKIE['project-name']['secondDigest'] &&
       (!isset ($_COOKIE['project-name']['username']) ||
        (isset ($_COOKIE['project-name']['username']) &&
         Users::checkCredentials($_COOKIE['project-name']['username'],
                                 $_COOKIE['project-name']['digest']))))
   {
      // Regenerate the ID to prevent session fixation
      session_regenerate_id ();

      // Restore the session variables, if they don't exist
      if (!isset ($_SESSION['project-name']['userID']))
      {
         $_SESSION['project-name']['userID'] = $_COOKIE['project-name']['userID'];
      }

      // Only redirect us if we're not already on a secured page and are not
      // receiving a logout request
      if (!isSecuredPage ($page) &&
          $action != 'logout')
      {
         header ('Location: ./');

         exit;
      }
   }
   else
   {
      // If we're not already the login page, redirect us to the login page
      if ($page != Page::LOGIN)
      {
         header ('Location: login.php');

         exit;
      }
   }

   // If we're not already logged in, check if we're trying to login or logout
   if ($page == Page::LOGIN && $action != '')
   {
      switch ($action)
      {
         case 'login':
         {
            $userData = Users::checkCredentials (stripslashes ($_POST['login-username']),
                                                 stripslashes ($_POST['password']));
            if ($userData[0] != 0)
            {
               $_SESSION['project-name']['userID'] = $userData[0];
               $_SESSION['project-name']['ip'] = $_SERVER['REMOTE_ADDR'];
               $_SESSION['project-name']['userAgent'] = $_SERVER['HTTP_USER_AGENT'];
               if (isset ($_POST['remember']))
               {
                  // We set a cookie if the user wants to remain logged in after the
                  // browser is closed
                  // This will leave the user logged in for 168 hours, or one week
                  setcookie('project-name[userID]', $userData[0], time () + (3600 * 168));
                  setcookie('project-name[username]',
                  $userData[1], time () + (3600 * 168));
                  setcookie('project-name[digest]', $userData[2], time () + (3600 * 168));
                  setcookie('project-name[secondDigest]',
                  DatabaseHelpers::blowfishCrypt($_SERVER['REMOTE_ADDR'] .
                                                 $_SERVER['HTTP_USER_AGENT'], 10), time () + (3600 * 168));
               }
               else
               {
                  setcookie('project-name[userID]', $userData[0], false);
                  setcookie('project-name[username]', '', false);
                  setcookie('project-name[digest]', '', false);
                  setcookie('project-name[secondDigest]',
                  DatabaseHelpers::blowfishCrypt($_SERVER['REMOTE_ADDR'] .
                                                 $_SERVER['HTTP_USER_AGENT'], 10), time () + (3600 * 168));
               }

               header ('Location: ./');

               exit;
            }
            else
            {
               $loginDiv = '<div id="login-box" class="error">The username or password ' .
                           'you entered is incorrect.</div>';
            }
            break;
         }
         // Destroy the session if we received a logout or don't know the action received
         case 'logout':
         default:
         {

            // Destroy all session and cookie variables
            $_SESSION = array ();
            setcookie('project-name[userID]', '', time () - (3600 * 168));
            setcookie('project-name[username]', '', time () - (3600 * 168));
            setcookie('project-name[digest]', '', time () - (3600 * 168));
            setcookie('project-name[secondDigest]', '', time () - (3600 * 168));

            // Destory the session
            session_destroy ();

            $loginDiv = '<div id="login-box" class="info">Thank you. Come again!</div>';

            break;
         }
      }
   }

   return $loginDiv;
}

Mi código:

<?php

function encrypt($input)
{
$hash = password_hash($input, PASSWORD_DEFAULT);
return $hash;
}

function checkUserCreds($username, $password)
{
    $id = 0;
    $hash = '';

    $db = new PDO('$dbDNS', '$dbuser', '$dbpass');
    $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); //Set error mode
    try
    {
        $st = $db->prepare("SELECT id, login, email, pass FROM users WHERE login =:username");      
        $st->bindParam(':username', $username, PDO::PARAM_STR);
        $success = $st->execute();

        if($success)
        {
            $userData = $st->fetch();
            $hash = $userData['pass'];
            if (password_verify($password, $hash) == $hash)
            {
                $id = $userData['id'];
            }           
        }

    }
    catch (PDOException $e)
    {
        $id = 0;
        $hash = '';
    }
    $db = null;

    return array ($id, $username, $hash);
}

function checkLoggedIn($page)
{
    $loginMess='';
    $action='';
    if (isset($_POST['action']))
    {
        $action = stripslashes($_POST['action']);
    }
    session_start();

    //Check if already logged in and check session information against cookies
    if (isset($_COOKIE['sukd']['id']) && encrypt($_SERVER['REMOTE_ADDR'] . $_SERVER['HTTP_USER_AGENT']) == $_COOKIE['sukd']['hashv2'] && (!isset ($_COOKIE['sukd']['username']) || (isset ($_COOKIE['sukd']['username']) && checkUserCreds($_COOKIE['sukd']['username'], $_COOKIE['sukd']['hash']))))
    {
        echo "isset cookies: ON, GOOD <br>";
        // Regenerate the ID to prevent session fixation
        //session_regenerate_id ();
    }   
    else
    {
        // If we are not on the login page, redirect.
        if ($page != 'login')
        {
            header ('Location login.php');
            exit;
        }
    }
    if ($page = 'login' && $action != '')
    {
        switch($action)
        {
            case 'login':
            {
                $userData = checkUserCreds(stripslashes($_POST['username']), stripslashes($_POST['password']));

                if ($userData[0] != 0)
                {
                    $_SESSION['sukd']['id']=$userData[0];
                    $_SESSION['sukd']['ip']=$_SERVER['REMOTE_ADDR'];
                    $_SESSION['sukd']['userAgent']=$_SERVER['HTTP_USER_AGENT'];
                    if(isset($_POST['remember']))
                    {
                        //remember for 7 days
                        setcookie('sukd[id]', $userData[0], time () + (3600 * 168));
                        setcookie('sukd[username]', $userData[1], time() + (3600 * 168));
                        setcookie('sukd[hash]', $userData[2], time() + (3600 * 168));
                        setcookie('sukd[hashv2]', encrypt($_SERVER['REMOTE_ADDR'] . $_SERVER['HTTP_USER_AGENT']), time () + (3600 * 168));
                    }
                    else
                    {
                        setcookie('sukd[id]', $userData[0], false);
                        setcookie('sukd[username]', '', false);
                        setcookie('sukd[hash]', '', false);
                        setcookie('sukd[hashv2]', encrypt($_SERVER['REMOTE_ADDR'] . $_SERVER['HTTP_USER_AGENT']), time () + (3600 * 168));
                    }

                    header ('Location: ./');

                    exit;
                }
                else
                {
                    $loginMess = "The username or password you entered is incorrect <br>";
                }
                break;              
            }
            case 'logout':
            default:
            {
                $_SESSION = array();
                setcookie('sukd[id]', '', time () + (3600 * 168));
                setcookie('sukd[username]', '', time() + (3600 * 168));
                setcookie('sukd[hash]', '', time() + (3600 * 168));
                setcookie('sukd[hashv2]', '', time () + (3600 * 168));

                session_destroy();

                $loginMess = "echo 'Successfully logged out <br>'";

                break;          
            }       
        }
    }
    return $loginMess;
}
?>

es llamado por checkLogged(login) por ejemplo, y que genera el mensaje de inicio de sesión si hay un problema. Además, utiliza un campo oculto con acción para establecer el valor, inicio de sesión o cierre de sesión para el cambio de caso. Actualmente, inicia sesión bien, agrega las cookies, etc.

Sin embargo, el problema es que cuando un usuario ya ha iniciado sesión, debería estar revisando el código.

if (isset($_COOKIE['sukd']['id']) && encrypt($_SERVER['REMOTE_ADDR'] etc..

Realmente no pude entender mucho el código original, así que ni siquiera estoy seguro de por dónde empezar. La matriz de cookies es un poco extraña, ya que parece estar basada en dos versiones diferentes en función de si configura la cookie o llama a la cookie.

Si alguien tiene un método más seguro sin pasarse de la raya, estoy feliz de que alguien me ilumine más sobre esto.

Original a mi código.

digest = hash
decondDigest = hashv2

preguntado el 21 de septiembre de 13 a las 12:09

2 Respuestas

No llamaría session_start(); dentro de la función. Si usa las cookies en cualquier otro lugar, las necesitará allí de todos modos. Téngalo al comienzo de su primer archivo en algún lugar antes que cualquier otra cosa.

Y tal vez usar esto:

if (!isset($_SESSION))
  {
    session_start();
  }

Si alguien tiene un método más seguro sin pasarse de la raya, estoy feliz de que alguien me ilumine más sobre esto.

¿Por qué no cambiar a $_SESSIONs?

El uso de cookies es completamente complicado para tratar de hacerlo seguro y, por lo tanto, los usuarios no pueden configurar ciertos datos por sí mismos, ya que está luchando ahora. Por el contrario, no puedo establecer una $_SESSION en su servidor.

Luego, en un ejemplo muy básico:

//your login script
//if logged in successful:
$_SESSION['loggedin']['username']=$username; //from DB
$_SESSION['loggedin']['whatever']=$whatever;

//Then your login check just checks the session
if (!isset($_SESSION['loggedin']))
  {
    //redirect to login page or don't server them user stuff
  }

Entonces no necesita molestarse con el hash de los datos que no quiere que vean, etc. Dependiendo de sus requisitos de seguridad, puede verificar y configurar varias cosas en las sesiones.

Es importante destacar que, como lo tiene actualmente, mientras verifica algunos detalles en la cookie, las personas pueden configurar sus propias cookies, lo que significa que su código podría simplemente verificar una cookie que un usuario ha configurado y pensar que está conectado y darles acceso a las cosas , tal vez la cuenta de otro usuario.

Las sesiones, aunque no son 100% seguras en el sentido de que nada lo es, son bastante seguras ya que se almacenan en el servidor fuera de la raíz web, lo que significa que para que alguien juegue con ellas, ya estarían en el servidor, y establecer sesiones es lo último que necesitan hacer para causar estragos.

Respondido el 21 de Septiembre de 13 a las 13:09

Preferiría usar un poco de ambos, no creo que alguien pueda usar cookies fácilmente, ya que he usado una combinación de la dirección IP y el agente de usuario HTTP que en sí mismo tiene hash y se verificará con el usuario. El problema es que no puedo descifrar el isset en el tutorial para que coincida con el mío. - omega_prime

Entonces, si configuro un archivo de cookies en mi propia máquina con mi dirección IP y el agente de usuario HTTP, ¿qué verifica? ¿Solo que existe en la cookie y coincide con la mía? ¿Cómo es eso un control de seguridad? Pondría mi propia cookie con lo que sea $_SERVER['REMOTE_ADDR'] y $_SERVER['HTTP_USER_AGENT'] establecería. Si esto es todo lo que hace, entonces cuando configuro mi cookie y configuro ['username'], puedo elegir el nombre de usuario de otra persona y me permitirás entrar. - James

El uso de cookies es completamente complicado para tratar de hacerlo seguro y, por lo tanto, los usuarios no pueden configurar ciertos datos, ya que está luchando ahora. Por el contrario, no puedo establecer un $_SESSION en su servidor. La sesión básicamente coincide con una identificación en una cookie de mi lado, si no hay una coincidencia de cookies de mi lado con una sesión en su servidor, entonces no tengo sesión (etc.). - James

Bueno, agrego la dirección IP + los datos del agente de usuario, los combino y luego los comparo. Lo he puesto como si fuera una contraseña, pero planteas un buen punto. Para ser honesto, realmente no necesito tanta seguridad, pero las sesiones, ¿cuánto impacto tienen en el servidor? Además, ¿las sesiones no presentan un problema cuando están en el mismo servidor que otras personas? ¿Y no caducan simplemente cuando cierras el navegador? El recuerdo parece crear las cookies, pero de lo contrario, creo que se almacena como una sesión. Como puede ver, $hash($input, password_default) es lo que uso para encriptar el agente de usuario + dirección IP: omega_prime

No es muy fácil adivinar que estoy de acuerdo, pero ¿no me registro e inicio de sesión y obtengo una cookie legítima de usted y jugueteo con ella para ver lo que ha hecho? Hay tantas cosas que podrías hacer hash que podría probar, nombre de usuario, contraseña, hora/fecha, IP, navegador. No tomaría mucho tiempo escribir un script rápido y sucio que tomara el hash legítimo en la cookie que configuraste para mí y lo comparara con una variedad de otras cosas con hash. Además, las direcciones IP de algunas personas cambian (carga equilibrada/compartida/otra configuración de red) - James

Descubrí la razón por la que no funcionaba. Estaba rehaciendo usando password_hash cuando debería haber estado usando password_verify. Esto significaba que daba una respuesta diferente cada vez.

Respondido el 21 de Septiembre de 13 a las 14:09

¡estupendo! Otra cosa para mencionar aquí, si proporciona una opción de cambio de contraseña, una vez que lo hagan, su verificador de inicio de sesión devolverá que no han iniciado sesión. Debe manejar eso limpiamente. Es decir, en la página de cambio de contraseña, actualice la cookie antes de verificar la función de inicio de sesión (etc.). (otra razón por la que hacerlo de la forma en que lo hace actualmente es complicado) - James

Muy cierto, solo pensé que se veía bastante bien, algunas de las ideas con $acción y cosas así. Solo lo he hecho en Java, pero lo hizo ver bastante limpio. Haga una pausa para pensar en los cambios de contraseña. Salud. - omega_prime

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.