PHP form token usage and handling
There is no need to do what you are attempting. When you start a session in PHP with session_start() a unique SESSIONID is already generated for you. You should not be putting this on the form. It is handled via cookies by default. There is also no need to check the SESSIONID either, that again is handled for you.
You are responsible for authenticating the user and storing their authenticated identity (e.g. $_SESSION['user_id'] = $userId in the SESSION. If a user logs out you destroy their session with session_destroy.
You should ensure session_start() is one of the first things for all pages in your site.
Here is a basic example:
<?php
session_start(); // starts new or resumes existing session
session_regenerate_id(true); // regenerates SESSIONID to prevent hijacking
function login($username, $password)
{
$user = new User();
if ($user->login($username, $password)) {
$_SESSION['user_id'] = $user->getId();
return true;
}
return false;
}
function logout()
{
session_destroy();
}
function isLoggedIn()
{
return isset($_SESSION['user_id']);
}
function generateFormHash($salt)
{
$hash = md5(mt_rand(1,1000000) . $salt);
$_SESSION['csrf_hash'] = $hash
return $hash;
}
function isValidFormHash($hash)
{
return $_SESSION['csrf_hash'] === $hash;
}
Edit: I misunderstood the original question. I added the relevant methods above for generating and validating form hashes;
Please see the following resources:
- PHP Session Handling
- session_start()
- session_destroy()
How can I pass a token generated on one PHP form to a form that processes it?
- Generate and save token in server side (sql or others..)
- Create cookie with the token (client side)
- When the form is submit, retrieve the token from cookie
- if the cookie is the same than the saved token, thats ok
Generate token:
$formName = "signin"; // name of the form
$ip = get_ip(); // create a function to get the ip of the user
$salt = "8077_(-(àyhvboyr(à"; // uniq secret salt
$token = md5(sha1($salt.$ip).sha1($salt.$formName));
...
if(empty($_COOKIE['token'])){ // if(empty($_SESSION['token'])){
setcookie("token",$token, time()+3600*1); // use with cookie // time()+3600*1 = now + 1 hour
$_SESSION['token'] = $token; // OR use with session
}else{
// when the form is submit regenerate the token and compare with the request token
if($_COOKIE['token'] == $token){ // OR if($_SESSION['token'] == $token){
// request from server - ok
// ...
}else{
// bad request
setcookie("token",0); // destruct cookie
$_SESSION['token'] = ""; // OR destruct session
// redirect at the first form
}
}
<form>
// if you want use the token directly in your form, add this :
<input type="hidden" name="token" value="<?php echo $token ?>" />
</form>
PHP Tokens for Forms and Authentication
Authentification mechanism creates a token when form displayed, and was stored it on server side.
Also auth mechanism adds token as hidden input to form. When you send it, auth system check is it in server-side storage.
If token found, authentification process will continue and token was removing.
It protects from spamming form action script.
Example using with logout url:
<?php
// Generate token
$logout_token = md5(microtime().random(100, 999));
session_start();
// Store token in session
if (!is_array($_SESSION['logout_tokens']) {
$_SESSION['logout_tokens'] = array();
}
$_SESSION['logout_tokens'][] = $logout_token;
?>
<a href="/logout/?logout_token=<?= $logout_token ?>">logout</a>
Script, that processing logout:
<?php
$done = false;
if (!empty($_GET['logout_token'])) {
// Get token from url
$logout_token = $_GET['logout_token'];
session_start();
if (!is_array($_SESSION['logout_tokens']) {
$_SESSION['logout_tokens'] = array();
}
// Search get token in session (server-side storage)
if (($key = array_search($logout_token, $_SESSION['logout_tokens'], true)) !== false) {
// Remove used token from storage
unset($_SESSION['logout_tokens'][$key]);
// Do logout
$done = true;
}
}
if ($done === false) {
echo "Something went wrong.";
}
Form action and antiCSRF token
Generally speaking, neither registration nor login forms need CSRF protection. Neither of them do anything with the logged-in user's personal data or authority. That said, there is no real reason to not have CSRF protection as you can write a generic system and apply it to every form on the site (unless you explicitly don't want CSRF protection, such as for search forms).
In order to prevent possible CSRF attacks i need to "save" the generated hash in a SESSION variable {$_SESSION['hashed_token'] = $_POST['hashed_token']}and then compare it to the value of the hash in the hidden form input field,
This is all sensible
after we redirect to main.php.
Don't do that. Put the code to do the comparison in a general function. Include it on all the form processing pages and run it when you process the form.
Related Topics
Adding a Namespace When Using Simplexmlelement
Decrypting Strings in Python That Were Encrypted with Mcrypt_Rijndael_256 in PHP
How to Select Multiple Rows from MySQL with One Query and Use Them in PHP
PHP Run Once and Insert Twice in MySQL Database
PHP Get Dropdown Value and Text
Jquery Mobile: Sending Data from One Page to the Another
PHP Unable to Load PHP_Curl.Dll Extension
Invoke External Shell Script from PHP and Get Its Process Id
How to View/Open a Word Document in My Browser Using with PHP or HTML
How to Display Special Characters in PHP
How to Run a .Sh File from PHP
Bubble Sort Implementation in PHP
Running Python Script in Laravel
File_Get_HTML Displays Fatal Error Call to Undefined Function