To understand the difference, we will examine in detail how each of the solutions and their security risks will work. In this example, we are going to store the number of page views of the user.
$ _ SESSION
We start a session, increase the counter and save it in the $_SESSION :
<?php session_start(); if(!isset($_SESSION["pageviews"])) { $_SESSION["pageviews"] = 0; } $_SESSION["pageviews"]++; ?>
When the user first visits this page, PHP generates a random session identifier that looks like this, and ask the browser to save this identifier in a cookie:
fh4giqncq25ntgs7gjunvj6i33
On the server, it will save and remember that there is a pageviews variable with a value of 1 , which belongs to the session identifier fh4giqncq25ntgs7gjunvj6i33 .
The next time a user visits the page, his or her browser will send the previous session identifier along with the request (given that the cookie has not expired or has been deleted). PHP then recognizes this identifier and populates the $_SESSION pageviews = 1 $_SESSION , then increments it: pageviews = 2
From a security perspective, consider the following questions:
Can a user read stored data? No - The only thing the client sees is a random session identifier in the cookie; the data itself is stored on the server.
Is the user available to modify or manage stored data? Again, no - If the session ID is changed in the browser, PHP will no longer be able to bind the browser to the stored data. In this worst case, the user will get a new session, starting with pageviews = 1 .
The main risk of session security is session hijacking , when an attacker manages to obtain a session identifier from another browser, and then presents it to the server, thereby posing as another user. In our example, this does not make much sense, since we only save the number of page views; however, most sites use sessions to track which user is logged into which browser. In this case, stealing another session will mean gaining access to their account.
Hidden field
In this case, we have a form with a hidden field:
<form action="..." method="post"> <input type="hidden" name="pageviews" value="<?php print($pageviews); ?>" /> ... </form>
On the server, we extract the pageviews variable from $_POST and increase it:
<?php $pageviews = @$_POST["pageviews"]; $pageviews++; ?>
So, instead of storing it on the server, we essentially send data to the client and expect it in a subsequent request. Besides the fact that it only works with POST requests, consider the security-related lower parts of this solution:
Can a user read stored data? Yes - it goes directly to the browser in HTML code.
Is the user available to modify or manage stored data? Yes - there is nothing that would prevent the user from opening developer tools in his browser and changing the hidden value no matter what he likes. After submitting the form, the server receives the modified data.
The problem with <input type="hidden"> is that you simply cannot trust the client , so you need to check the data that you receive in each request. In some cases, this may be reasonable, for example, filling out multi-page forms, but even this can often be better resolved through sessions.
Summary
Stored data through $_SESSION usually safer than using <input type="hidden"> because session data is stored on the server and therefore cannot be changed by the client. The browser uses only a random session identifier that associates data on the server with this particular browser.