1

I've searched and found a thousand questions about my problem, I have tried to solve but have not been of help. So I open this thread for my particular case, and I hope you can help me.

I come to the point, I am creating a login system in PDO, are a beginner, but I wish it would last login via cookies for a total time.

I did several tests, but no result. The browser is closed, they had to be re-entered credentials.

I repeat, I already searched on the site, but have not managed to solve.

login.php

if (empty($_POST) === false) {
    $username = trim($_POST['username']);
    $password = trim($_POST['password']);

    if (empty($username) === true || empty($password) === true) {
        $errors[] = 'Sorry, but we need your username and password.';

    } else if ($users->user_exists($username) === false) {
        $errors[] = 'Sorry that username doesn\'t exists.';

    } else if ($users->email_confirmed($username) === false) {
        $errors[] = 'Sorry, but you need to activate your account. Please check your email.';

    } else {

        $login = $users->login($username, $password);

        if ($login === false) {
            $errors[] = 'Sorry, that username/password is invalid';    
        } else {
            $_SESSION['id'] =  $login; // The user's id is now set into the user's session  in the form of $_SESSION['id']
            $_SESSION['username'] = $usr;

                $cookie_name = '_name_cookie_';         
                $hash = password_hash($password, PASSWORD_BCRYPT, ["cost" => 12]); // will result in a 32 characters hash
                $cookie_time = (3600 * 24 * 30); // 30 days
                setcookie($cookie_name, 'usr='.$usr.'&hash='.$hash, time() + $cookie_time);    


            header('Location: home.php');
            exit();
        }
    }
}

class: users.php

public function login($username, $password) {
    $this->db->query("SELECT * FROM users WHERE username = :username");
    $this->db->bind(':username', $username);
    $data = $this->db->single();

    $hash = $data['password'];
    $id = $data['id'];

    #hashing the supplied password and comparing it with the stored hashed password.
    if (password_verify($password, $hash)) {
        return $id; 
    }else{
        return false; 
    }
}

NOTE: in form at the moment I do not care to integrate check "Remember Me", I'll do it later.

However, I can not how to stay logged in user, the cookie is inserted properly but otherwise it does not work. how do I fix?

  • do you call session_start() at the beginning of every file? My login system works exactly as you want it to. I can show you how I handle sessions, but I dont know if this is what you want – JRsz Jun 10 '16 at 10:20
  • That's not the problem, session_start () is called on every page, the login will last, however limited. I would like to record user data, so I do not always enter your details to log in. – Marco Bonanno Jun 10 '16 at 11:52

2 Answers2

1

There are several approaches to do this, some better than others. There's some information on it, even on this website, but I'll outlay the general idea.

First off, you'll need some sort of token or something to recognize the user on a client-side. This is usually done with use of $_COOKIE. I like to set two separate cookies, one with the user-ID and one with a hashed token, so that even if someone could guess the token (which is highly unlikely), they'd also need the matching user-ID. Using examples from your code, this would be sample-code to generate said cookies

// Define variables
define("COOKIE_DURATION", time()+60*60*24*30); // 30 days
$userHash = hash("sha256", $_SESSION['id'].time());

// Set the cookies
setcookie("RememberMeID", $_SESSION['id'], COOKIE_DURATION);
setcookie("RememberMeHash", $userHash, COOKIE_DURATION);

This uses the current time and the username combined, then hash that so we can use it as an identifier. I've used sha256 for this, as it isn't a password we're storing, that should be fine.

Next, we need to recognize the user with these two cookies. So this data has to be stored in the server as well, so we can match them when the user visits the website. You can use a database for this, for example a separate rememberMe table containing this information. This could contain the hash you created before, with the users id. So, you'll need to insert that into the database.

$stmt = $pdo->prepare("INSERT INTO rememberMe (userID, userHash) VALUES (:id, :hash)");
$stmt->execute(array("id" => $_SESSION['id'], "hash" => $userHash));

Then, you can simply check if both cookies are set, while a session isn't set, see if the data matches - and if it does, set their session!

// If we're not logged in, and the two cookies are set, we can check if something matches
if (!isset($_SESSION['id']) && !empty($_COOKIE['RememberMeID']) && !empty($_COOKIE['RememberMeHash'])) {
    // Check if the cookies match something in the DB...
    $stmt = $pdo->prepare("SELECT COUNT(*) as `count`, userID FROM rememberMe WHERE userID=:id AND userHash=:hash");
    $stmt->execute(array("id" => $_COOKIE['RememberMeID'], "hash" => $_COOKIE['RememberMeHash']));
    $row = $stmt->fetch(PDO::FETCH_ASSOC);

    // If it does, we log them in and renew the cookie
    if ($row['count'] > 0) {
        $_SESSION['id'] = $row['userID'];
        setcookie("RememberMeID", $_SESSION['id'], COOKIE_DURATION);
        setcookie("RememberMeHash", $_COOKIE['RememberMeHash'], COOKIE_DURATION);
    }
}

You can also have a read at this topic: What is the best way to implement "remember me" for a website?

Community
  • 1
  • 1
Qirel
  • 25,449
  • 7
  • 45
  • 62
0

thank you so much for your help. I am proceeding in this way at the time:

    if (empty($_POST) === false) {
    $username = trim($_POST['username']);
    $password = trim($_POST['password']);

    if (empty($username) === true || empty($password) === true) {
        $errors[] = 'Sorry, but we need your username and password.';

    } else if ($users->user_exists($username) === false) {
        $errors[] = 'Sorry that username doesn\'t exists.';

    } else if ($users->email_confirmed($username) === false) {
        $errors[] = 'Sorry, but you need to activate your account. Please check your email.';

    } else {

        $login = $users->login($username, $password);

        if ($login === false) {
            $errors[] = 'Sorry, that username/password is invalid';    
        } else {

            if (!isset($_SESSION['id']) && !empty($_COOKIE['RememberMeID']) && !empty($_COOKIE['RememberMeHash'])) {
                $db->query("SELECT * FROM rememberMe WHERE userID = :userID AND userHash = :userHash");
                $db->bind(':userID', $_COOKIE['RememberMeID']);
                $db->bind(':userHash', $_COOKIE['RememberMeHash']);
                $db->resultset();
                $row = $db->rowCount();

                if ($row['count'] > 0) {
                    $_SESSION['id'] = $login;
                    setcookie("RememberMeID", $_SESSION['id'], COOKIE_DURATION);
                    setcookie("RememberMeHash", $_COOKIE['RememberMeHash'], COOKIE_DURATION);
                    header('Location: home.php');
                    exit();     
                }
            }
        }
    }
}

While, I was wondering where to enter the first code and at what time. In effect, the code for the insertion of the token must be inserted for example in the registration page, so that the registering user are entered into the database?