User authentication on the site. Sessions and cookies

Features of the HTTP protocol
As you learned in the last chapter, web sites on the Internet are handled over the HTTP protocol.
It is a wonderful and simple protocol that operates on a request-response basis. That is, the user's client (browser) sends a request to the server, which, as a rule, consists only of headers, and then receives a response in the form of response headers and the body of the document itself.
Unlike many other protocols, HTTP is stateless. This means that there is no preservation of an intermediate state between request-response pairs.
In other words, the server does not “remember” clients; it processes each request from scratch.
For the server, there is no difference: one user has requested a page ten times or ten different users at a time. For him, all requests are the same.
Why is this inconvenient for us?
Sites often need to be able to identify their visitors in order to save and show them later any information.
For example, online retailers can save browsing history to recommend products that best suit them to potential customers. Or a news aggregator might prompt users to select only the headings they are interested in.
Fortunately, the HTTP protocol, as well as all browsers, provide the ability to store user information.
Cookies
Cookies (hereinafter simply "cookies") are small pieces of data that a web server sends to the browser.
The browser stores them and sends them back the next time you visit the web page. Thanks to this, the web server will be able to recognize its "old" visitor and identify him.
Technically, cookies are regular HTTP headers.
When a web server wants to write a cookie to the user's browser, it sends a special response header with a name Set-Cookie
. This header should contain the necessary information and additional attributes, which will be discussed later.
The next time the user's browser requests a web page from the same site, it will pass the request header along with other headers Cookie
. The web server will receive this information and it will be available to PHP as well.
Example
The task is very simple: to save and show the page visitor how many times he has visited our site. To do this, we will save the number of visits in a separate cookie, increasing the values by one each time the page is loaded.
How to set cookies: the setcookie function
As a server-side programming language, PHP can manage the headers that the server sends, which means it can set and read cookies.
To add a new cookie, you must first decide on the following criteria:
- The name of this cookie (can only consist of Latin characters and numbers);
- The value to be stored;
- The lifetime of the cookie is imperative.
A function is responsible for setting cookies in PHP setcookie
; it needs to pass at least three parameters described above. Example:
So, to get the contents of a cookie named "visit_count", you just need to refer to the array element of the same name $_COOKIE
, for example, like this:
Sessions, aka sessions, are, in fact, just a convenient wrapper over cookies. They also allow you to store data relevant to the user, but with some differences and limitations:
- The data is not stored for an arbitrary time, but only until the tab with the web page is closed.
- For sessions to work, a function must be called at the beginning of each script
session_start()
. - The available storage space is much larger.
Writing and reading information when using sessions looks like working with a special array $_SESSION
.
How sessions work
- PHP generates a unique browser ID.
- The identifier is stored in a special cookie and transmitted with each request.
- All data that is written to the session is automatically saved by PHP in a special file on the server.
Thanks to the existence of sessions in PHP, we can save any data as easily as assigning it to variables. But, unlike variables, this data will persist for the user between requests within the session.
Let's rewrite the script for counting visits, but now we use sessions:
Public pages include catalog pages, product information, delivery terms, and so on. Private - shopping cart, order history.
It is quite obvious that each customer should have their own shopping basket, and only the owner himself and no one else should have access to it.
The procedure for checking the ability of a user to access a specific part of the site is called authentication.
The entire authentication process always consists of several steps:
- When trying to access the closed part of the site, the user sees a form where he must enter his username and password.
- The form is submitted and the received data is compared with the valid login and password of the existing user.
- If the data match, then the user is considered authenticated and gets access to the private part of the site.
- When re-opening this page, the user does not have to re-enter the password if he has already done so in the current session.
A little more terminology
A distinction should be made between two terms: authentication and authorization.
Authentication - checking the authenticity of the identifier provided by the user (login-password pair).
Authorization is the process of checking and granting rights to a user to perform a certain action.
In the online store example, authentication is performed when the user fills out the login form and enters their personal account. The script that processes the form only verifies that such a user exists and that his password matches.
Authorization comes into play when the user performs some action. For example, it removes an item from its cart. During this action, the script should check if the item belongs to this user's cart. Without such a check, the user could delete an item from someone else's cart.
The authorization logic is much more complicated than a simple check of the coincidence of mail and password when entering the site. Authorization can also include the following concepts: user groups, types of actions, resources, hierarchy of roles and actions. A separate chapter can be devoted to this topic. We will not cover authorization in this tutorial because this topic is beyond the "basic" one.
registration on the site
Before we start adding authentication to our site, we need to add a form to register a new account.
An account is a user account.
To create an account, you need to register - this is filling out a special form where the user indicates his mail, password, and, possibly, additional information.
After registration, all data from the form is saved in the database as is. But you need to pay special attention to storing passwords.
Storing passwords
The user password is a secret set of characters that is used later in the course of authentication. Knowing the user's password, an attacker can enter the site under his name. For this reason, the password cannot be stored in the database in clear text. After all, if information from the site's database is stolen, then the data of all users will become compromised.
Instead of the password itself, their fingerprints - hashes - will be stored in the database.
What is hashing
The fingerprint (hash) is the result of the hashing function, which will return a fixed-length string for any value.
Using a special mathematical algorithm, such a function is able to convert any transmitted information to a string of fixed length (for example, 32 or 64 characters). Moreover, any array of information, be it all articles from Wikipedia, or one word, will always correspond to a unique imprint. A repeated function call for the same source always returns the same hash.
The reverse operation (to get the original from the print) is impossible.
Let's take a simple example. We have information for which we want to get a fingerprint. Let the following line be such information:
“I only know that I don’t know anything, but others don’t know this either”
The result of processing this string with the SHA-1 hashing function will be as follows:6b3cb0df50fe814dee886b4e1c747dda6ce88b37
Hashing functions are often used to check the integrity of information as it travels over a network. For example, to make sure that the uploaded file was not damaged, it is enough to get its hash and compare this hash with the one published on the site. If at least one byte has changed in the file, then these prints will be completely different.
Hash functions will help us to compare passwords.
Implementing user registration
Let's go back to the registration form.
It was said above that instead of a password, it is better to store his fingerprint. There are many hashing functions for obtaining a fingerprint. Fortunately, we don't need to understand their diversity, because PHP has a standard function that does exactly what it needs to do.
Here is an example of how to get a fingerprint from a password that can be stored in a database:
$passwordHash = password_hash('iloveponies', PASSWORD_DEFAULT);
Calling this function will return the following line: $2y$10$a1pgDBerBsqD24D7qOAsl.QFTvwxQQGe4r1oWhD7f9yEnDvx4i7tW
It is this value that should be stored in the database, instead of a password.
Password check when entering the site
After registration, the user has his own account on the site, and he can use it. This means that now you need to create a login form. The form will check the correctness of the entered username and password to give the user access to restricted parts of the site.
First, we are looking for a record in the table with users with an E-mail equal to that received from the form. If such an entry exists, then the next step is to verify that the password is correct.
There is a function to compare a password with its hash password_verify
. A password and a hash is passed to it, with which the given password must be compared. The function will return true
or false
depending on the result of the comparison:
$res = password_verify('bad-password', $passwordHash);
Using a session to control access
Sessions are most often used to store information about the logged in user. The principle of operation here is very simple: inside the script responsible for processing the login form, a new session is opened, where information about the logged in user is recorded. Such information can be an associative array with all values from the corresponding record from the database.
Next, we'll add some code to check for the existence of a session in scripts that should be closed from anonymous users. If the session is empty, then this user did not log into the site, and he does not have access to this page.
In this case, you can return a 403 response code and display an error message, or force a redirect to the home page.
Log out from the site
If the site has an entrance, then there must be an exit. This output will be a special script that will clear the session and redirect to the main page.
To clear the session, it is enough to clear the array $_SESSION
:$_SESSION = []