With the increase in online attacks, password security is becoming more and more important. As developers we are responsible for managing security, calculating hashes, and storing user passwords, whether the application is a simple game or a repository of top-secret business documents. PHP has some built-in tools that make protecting passwords easier. In this section we will discuss how to use these tools according to modern security measures.
1. Three principles of password protection
We must never know the user’s password
We must never know the user’s password. There should also be no way to obtain user passwords. If your application's database is hacked, you don't want plain text or decryptable passwords in the database. At any time, the less you know, the safer you are.
Never restrict the user’s password
If the password is required to conform to a specific pattern, it actually provides a way for people with bad intentions to attack the application. If it must be restricted For passwords, I recommend only limiting them to a minimum length. It is also a good idea to blacklist commonly used passwords or passwords created based on a dictionary.
Never send a user password via email
If you email a user a password, the user will know three things: you know his password, and you Having stored his password in plain text or in a way that can be decrypted, you don't have to worry about sending plain text passwords over the Internet.
We should send the URL for setting or changing the password in the email. Web applications usually generate a unique token. This token is only used once when setting or changing the password (such as changing the password). ), usually we use this token as a parameter of the URL to set or change the password. When the user accesses this URL, the application will verify whether the token is valid. If it is valid, continue the operation. After the operation is completed, the token becomes invalid and cannot be reused. .
2. Password storage algorithm
The best practice regarding password storage is to calculate the hash value of the password rather than encrypting the user's password. Encryption and hashing are not the same thing. Encryption is a two-way algorithm. Encrypted data can be decrypted, while hashing is a one-way algorithm. The hashed data cannot be restored to the original value, and the hash value obtained for the same data is always the same. same.
To store the user's password in the database, you must first calculate the hash value of the password, and then store the hash value of the password in the database. If a hacker breaks into the database, he will only see meaningless password hashes. value, it would take a lot of time and NSA resources to crack.
There are many kinds of hashing algorithms (such as md5, SHA1, bcrypt and scrypt). Some algorithms are very fast and are used to verify data integrity; some algorithms are very slow and are designed to improve security. Use slow, highly secure algorithms when generating and storing passwords.
Currently, the most secure algorithm is bcrypt. Unlike md5 and SHA1, bcrypt is deliberately designed to be very slow. bcrypt will automatically add salt to prevent potential rainbow table attacks. The bcrypt algorithm will cost a lot of money. The data is processed repeatedly over time to generate a particularly secure hash. In this process, the number of times data is processed is called the work factor. The higher the value of the work factor, the longer it takes to crack the password and the better the security. The bcrypt algorithm is timeless. If computers become faster, we only need to increase the value of the work factor.
3. Password Hash API
Through the previous introduction, we know that there are many things to consider when processing user passwords. Fortunately, PHP 5.5.0 native The Hash API (http://php.net/manual/zh/book.password.php) provides many easy-to-use functions, which greatly simplifies the operation of calculating password hashes and verifying passwords. Moreover, this password hash The API uses the bcrpt algorithm by default.
When developing web applications, there are two places where the password hashing API will be used: registered users and user login. Let's take the user registration and login provided by Laravel as an example to take a look at the PHP password hashing API. How to simplify these two operations.
Note: The built-in user registration and login functions of the Laraval framework use the PHP hash API to store and verify passwords.
Registered users
User registration is completed in AuthController, and the creation of new users is implemented in the create method of the controller:
You can see that the auxiliary function bcrypt provided by Laravel is used to hash the password submitted by the user and save it to the database. The bcrypt function is defined as follows:
Here we can see that the make method on the service provider instance aliased as hash is actually called to implement the hashed password and enter the HashServiceProvider. In the register method, we can see that the class corresponding to hash is BcryptHasher, and in this class we find the make method:
The core here is to call the password_hash function provided by PHP. This function receives three parameters. The first is the password value entered by the user, and the second parameter is the hash algorithm used (see more algorithms: http: //php.net/manual/zh/password.constants.php), the third parameter is optional, including salt and cost options, which respectively represent the interference string (salt) and the previously mentioned work factor, work The factor can be increased with the improvement of hardware performance. If not, use random salt and default working factor (calculating the hash value generally takes 0.1 to 0.5s). If the calculation fails, an exception is thrown.
User login
In Larval, take the example of using session as guards and eloquent as providers in auth.php to implement user login authentication (actually the default settings are like this ), login verification will eventually go to the validateCredentials method of EloquentUserProvider:
$this->The corresponding implementation of hasher is also the BcryptHasher class, let’s check its check method:
The first parameter passed in is the password entered by the user, and the second parameter is the password hash value saved when the user registered. If the hash value is empty, directly Return false, otherwise the password_verify function provided by PHP is called. This function is used to verify whether the password (plain text) and the hash value match. The match returns true, otherwise it returns false.
Recalculate the hash value
Through the above steps, the user can already achieve login authentication, but before logging in, we also need to check whether the existing password hash value has been Expired. If expired, the password hash needs to be recalculated.
Why do we need to recalculate? The application that joined us was created two years ago and used a work factor of 10. Now it uses 20 because computers are faster and hackers are smarter. Some users' password hash values may still be generated when the work factor is 10. In this case, after the login authentication is passed, the password_needs_refresh function must be used to check whether the existing hash value in the user record needs to be updated. This function can ensure that the specified Password hashes are created using the latest hashing algorithms. If you really need to recalculate the hash value of the generated password, use the make method to generate a new hash value and update the original password in the database.
This feature is not currently used in Laraval, but the corresponding function has been provided in the BcryptHasher class:
Original address: https ://xueyuanjun.com/post/4764
The above is the detailed content of How do PHP developers do password protection and Laravel's underlying password storage and verification implementation?. For more information, please follow other related articles on the PHP Chinese website!