For password security, developers need to:
1, absolutely can not know the user's password, we must encrypt the user's password, can not save the user's original password directly in the database.
2, do not limit the user password format, if the format is specified, it is likely to be exploited and cracked by the attacker, of course, we need to limit the minimum length of the password, it is recommended to at least 8 bits, the longer the better.
3, can not send the user password through the mailbox, when we develop the application to retrieve the password, the user password is not notified to the user by email, but the link to reset the password is sent to the user in the form of mail, let the user Go to reset the password.
MD5 with salt and safety
PHP developers are familiar with the md5() function. Many developers use md5('abc123') to encrypt user passwords. This is not wrong, but the security is still very low, because many users of the website. The data is encrypted with md5, so there is a collision event. The most typical one is the user information disclosure incident on the 12306 train ticket website in previous years. Many people use the same password on multiple websites. The hacker finds that the user password of station A and the password of station B are the same, so the password of station A is registered on station B. On the other hand, the md5 algorithm can be cracked very early, so md5 processing alone is not safe.
Then we can use md5 plus salt to enhance the encrypted password security, salt and salt value, this value should be generated randomly, can be generated together with the password and saved to the database when the user registers, and then the user login verification The password and salt value are combined and verified together.
$password = '1dhsh#sdLs';
$salt = randStr();
$md5pass = md5('goocode'.$password.$salt);
function randStr($length = 8){
$randpwd = '';
for ($i = 0; $i < $length; $i++){
$randpwd .= chr(mt_rand(33, 126));
}
return $randpwd;
}
The above code mixes the password with the salt value and the constant, then md5 to a complex encrypted string, and then saves the encrypted string $md5pass and the salt value $salt to the data table. Come out, combine in the same way, if the combined encrypted string is the same as the $md5pass value in the data table, then the verification is successful. In general, it is still very difficult to set up a relatively complicated password and salt processing.
Password_hash password hash and security
When PHP version >= 5.5, password_hash() and password_verify() can be used to encrypt and verify the user's password.
For password salting, the password_hash function now uses the most powerful encryption algorithm BCrypt currently supported by PHP. Of course, this function will support more encryption algorithms in the future. In fact, password_hash() has helped us to process the salt. The added random substring is automatically saved by the encryption algorithm and becomes part of the hash. Password_verify() extracts random substrings from it, so you don't have to use another database to record these random substrings, greatly simplifying the operation of calculating password hashes and verifying passwords.
We use examples to familiarize ourselves with the use of password_hash.
First look at the registered user register.php section.
<?php
Try {
// Verify email
$email = filter_input(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL);
If (!$email) {
Throw new Exception('Illegal Email');
}
// verify password
$password = filter_input(INPUT_POST, 'password');
If (!$password || mb_strlen($password) < 8) {
Throw new Exception ('password length must be greater than 8 digits');
}
/ / Check if the username already exists
$sql = "SELECT username FROM user WHERE username=:username";
$stmt = $db->prepare($sql);
$stmt->execute(array(
':username' => $email
));
$row = $stmt->fetch(PDO::FETCH_ASSOC);
If ($row) {
Exit('User Email already exists');
}
/ / Create a password hash value
$passwordHash = password_hash(
$password,
PASSWORD_DEFAULT,
['cost' => 12]
);
If ($passwordHash === false) {
Throw new Exception('Password hash failed');
}
$sql_insert = "INSERT INTO `user` (username,password) VALUES (:username,:password)";
$stmt = $db->prepare($sql_insert);
$stmt->execute(array(
':username' => $email,
':password' => $passwordHash,
));
$insert_id = $db->lastinsertid();
If ($insert_id) {
// redirect to the login page
Header('HTTP/1.1 302 Redirect');
Header('Location: login.html');
}
} catch (Exception $e) {
// Report error
Header('HTTP/1.1 400 Bad request');
Echo $e->getMessage();
}
Let's look at the login verification login.php section.
In the above code, the user's email and password are first verified, and if they do not match, an exception is thrown. Then use the password_hash() function to create a password hash. The first argument to this function is a plain text password; the second argument is the PASSWORD_DEFAULT constant, which tells PHP to use the bcrypt hash algorithm; the third argument is an array specifying Hash option, the cost in this array is used to set the working factor. The default is 10, which can be increased according to hardware capabilities. Finally create an account to write data to the data table.
<?php
Session_start();
Try {
// Get post email
$email = filter_input(INPUT_POST, 'email');
/ / Get the login password
$password = filter_input(INPUT_POST, 'password');
// Find users
$sql = "SELECT id, password FROM user WHERE username=:username";
$stmt = $db->prepare($sql);
$stmt->execute(array(
':username' => $email
));
$row = $stmt->fetch(PDO::FETCH_ASSOC);
If (!$row) {
Exit('User does not exist');
}
// verify password
If (password_verify($password, $row['password']) === false) {
Exit('Password error!');
}
/ / Save the session session
$_SESSION['user_logged_in'] = 'yes';
$_SESSION['user_email'] = $email;
// redirect jump
Header('HTTP/1.1 302 Redirect');
Header('Location: user.php');
} catch (Exception $e) {
Header('HTTP/1.1 401 Unauthorized');
Echo $e->getMessage();
}
The above code first obtains the user's email and password, and then searches for the email in the data table according to the email. If it exists, the encrypted password hash is taken out at the registration; then the password is verified by the password_verify() function, and the password_verify() function has two Parameters, the first parameter is a plain text password, and the second parameter is the password hash value read in the user data table. If the function returns true, the password is correct. Otherwise, the password is incorrect and the login is terminated.
After a period of time, we want to enhance the user encrypted hash password. You can use password_needs_rehash to check whether the user password hash needs to be updated, such as increasing the working factor from 10 to 20, and recalculating the password hash. To make passwords more secure.
If your php version is between 5.3.7 and 5.5, you can use the alternative to password_hash: password compat.