简体   繁体   中英

Is this safe enough for user login and verification? (PHP, MySQL, Sessions)

Just want to make sure I have not missed anything obvious. Need your guys expertise on this.

User data in database: - Password is stored as a crypt() that is salted with salt string that is stored in user table.

Sessions: - When user logs on correctly I create a new row in a sessions table with a unique sha256 hash session ID. I store user_id there too to see what session exists to what user. - I create a cookie which I store the session ID in. - Session is removed when user logs out by accessing logout function. - Session is automatically deleted on a defined expiration time (eg 7 days)

Authentication: - Check if client has a cookie with session ID in it. If the cookie session ID matches a session ID in sessions table, user is authenticated.

What do you guys think? Do I need to do something else about it?

EDIT: Added the method to generate the password:

public function generate_salt($password) {
    $cost = $this->CONFIG['user__password_encrypt_cost'];
    $salt = strtr(base64_encode(mcrypt_create_iv(16, MCRYPT_DEV_URANDOM)), '+', '.');

    // Prefix information about the hash so PHP knows how to verify it later.
    // "$2a$" Means we're using the Blowfish algorithm. The following two digits are the cost parameter.
    $salt = sprintf("$2a$%02d$", $cost) . $salt;

    // Hash the password with the salt
    $hash = crypt($password, $salt);


    return array(
        'salted_password' => $hash,
        'salt' => $salt
     );
}

Crypt with CRYPT_SHA512 and salt is secure, however usage of password_hash() is recommended.

Crypt with MD5 or similar weak hashing should not be used.

The session handling is overcomplicated.

PHP has session handling where you can store the cookie (it stores it actually automatically). In the session you can add a user id

$_SESSION['userid'] = $sUserIdFromDB;

If the client has a cookie it will find the session data and you can check if he is logged in.

if (isset($_SESSION['userid']) 
    AND is_int($_SESSION['userid']) AND (0 < $_SESSION['userid'])) {
    $oUserRow = $oDB->getByID($_SESSION['userid']);
} else {
   // user is not logged in (has no valid session)
}

Storing the Session ID in DB is possible but adds another additional request to DB which is not necessary. It does not increase security. Actually you will find issues where users log in from two different browsers at same time (mobile and desktop, mobile API) using the DB approach as the Session ID will be different.

More important is: - every user should have a different salt - enforce minimum length of passwords (8chars) - enforce large variety of characters used (lowercase, uppercase, numbers, special chars) - allow secure resetting of new password (no password should be sent by email) - ....

"Safe enough" is a little difficult to answer but here are some other things to consider:

  1. Salt strength -- is it the username or is it a random value or time stamp? Prefer the latter two.
  2. Are you requiring SSL when the password is sent over the wire? Consider doing this.
  3. Is the cookie 'Secure' and 'HttpOnly' to mitigate CSRF? Do this if you can (depends on client support).
  4. Are employees restricted from accessing both the salt and the encrypted value? Restrict who has access to any sensitive information.
  5. Which encryption algorithm and how many bits? Try DES 512 or stronger.
  6. Do you enforce password strength requirements? You should!
  7. Is the DB connection secure? Important especially if the DB link is over a WAN.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM