sanjsimi Posted May 2, 2017 Share Posted May 2, 2017 Hi, i'm making a contact form with hidden field that will create token and store it in session so i can prevent form spaming and other things. But i'm facing problem because i don't know how to check token from session with password_verify() function. <?php error_reporting(E_ALL); session_start(); function create_token() { $_SESSION['token'] = password_hash(mt_rand(5,99), PASSWORD_DEFAULT); return $_SESSION['token']; } function validate_token($token) { if (isset($_SESSION['token']) && !empty($_SESSION['token'])) { $token = $_SESSION['token']; if (password_verify($token, $_SESSION['token'])) { return true; } } else { return false; } } function delete_token($token) { if (isset($_SESSION['token']) && !empty($_SESSION['token'])) { session_destroy($_SESSION['token']); $_SESSION['token'] = ''; return true; } } if (isset($_POST['submit'])) { $name = $_POST['name']; $email = $_POST['email']; $subject = $_POST['subject']; $message = $_POST['message']; $token = $_POST['token']; if (validate_token($token) === true) { echo "valid token"; delete_token($token); } else { echo "invalid token"; } } ?> <!DOCTYPE html> <html> <head> <title>Contact form</title> <style type="text/css"> body { background-color: #f1f1f1; } form { font-family: Tahoma, Arial, sans-serif; font-size: 12px; border: 1px solid #e2e2e2; width: 286px; margin: 0 auto; padding: 20px; background-color: #fff; } label { display: block; padding: 0 0 5px 0; font-weight: bold; } input, textarea { padding: 4px; width: 285px; margin: 0 0 10px 0; border: 1px solid #e2e2e2; font-size: 12px; background-color:#f7f7f7; } input:focus, textarea:focus { border:1px solid steelblue; } textarea { min-height: 100px; height: 100px; } input[type="submit"] { width: 286px; padding: 10px; color: #fff; background-color: steelblue; border: none; } .required { font-weight: bolder; color: red; } </style> </head> <body> <form action="" method="POST"> <h2>Contact us</h2> <p>All fields marked with an <span class="required">*</span> are required</p> <label for="name">Name <span class="required">*</span></label> <input type="text" name="name" id="name"><br /> <label for="email">Email <span class="required">*</span></label> <input type="email" name="email" id="email"><br /> <label for="subject">Subject <span class="required">*</span></label> <input type="text" name="subject" id="subject"><br /> <label for="message">Message <span class="required">*</span></label> <textarea name="message" id="message"></textarea><br /> <input type="hidden" name="token" value="<?php echo create_token(); ?>"> <input type="submit" name="submit" value="Submit"> </form> </body> </html> Quote Link to comment Share on other sites More sharing options...
Solution requinix Posted May 2, 2017 Solution Share Posted May 2, 2017 Is this token a password? No? Then don't try to make it a password. All you need is a random value, so sha1(uniqid(time(), true))is sufficient. Put the value in the form and in the session, then compare the two values. Regular string comparison. Quote Link to comment Share on other sites More sharing options...
benanamen Posted May 2, 2017 Share Posted May 2, 2017 In reading the manual for uniqid, I see a big red box that says "Warning This function does not guarantee uniqueness of return value." Perhaps @Jaques1 can weigh in on this. Quote Link to comment Share on other sites More sharing options...
requinix Posted May 2, 2017 Share Posted May 2, 2017 I'm sure Jacques can find all sorts of reasons why what I posted is horrible. This token doesn't have to be globally unique. It's far more likely that someone would bypass the token mechanism itself than collisions becoming an issue. Quote Link to comment Share on other sites More sharing options...
ginerjm Posted May 2, 2017 Share Posted May 2, 2017 Can't it just be any random value? Such as "axbacx" or a RAND function value? It just has to be a value that you can store in the session and hidden on the form and nothing terribly unique. Quote Link to comment Share on other sites More sharing options...
sanjsimi Posted May 2, 2017 Author Share Posted May 2, 2017 This thing don't work with session, because when you store random value and put it in session, on form submition it create new random value and its not same like this in session Quote Link to comment Share on other sites More sharing options...
ginerjm Posted May 2, 2017 Share Posted May 2, 2017 YOu only create a token when you actually send out the form. At that point you create it, hide it on the form and save it in the session. Then when you receive the POST back you check it. 1 Quote Link to comment Share on other sites More sharing options...
requinix Posted May 2, 2017 Share Posted May 2, 2017 Can't it just be any random value?Pretty much. uniqid+time to get a unique-ish value, then sha1 to make it look random (check the actual value of uniqid+time sometime) as well as definitely HTML safe (the output being only letters and numbers). Such as "axbacx" or a RAND function value? It just has to be a value that you can store in the session and hidden on the form and nothing terribly unique."axbacx" is random, but the point here is an unpredictable random value. So something static won't work RAND/rand/mt_rand is just a random number, which is fine, except it's short and unintimidating. A little more effort would be nice. Quote Link to comment Share on other sites More sharing options...
ginerjm Posted May 2, 2017 Share Posted May 2, 2017 If that is the way you are going to do it, I would suggest two functions (saved in one module). One function to create the token value and to save it in the session and return it to the caller for use in the form. The other function to do the validation of the token upon the return of the form. That way should you want to alter anything you only need to modify the two functions and not have to worry about all the places you used them. Quote Link to comment Share on other sites More sharing options...
Jacques1 Posted May 2, 2017 Share Posted May 2, 2017 (edited) Guys, it's 2017. Even PHP has a proper randomness API now (as well as a polyfill for the users of PHP 5). The days where you could use kindergarten functions like this SHA-1 stuff without getting laughed at are over. <?php // include the random_compat library if you don't have PHP 7 yet const TOKEN_BYTE_COUNT = 16; function generate_token() { return bin2hex(random_bytes(TOKEN_BYTE_COUNT)); } Edited May 2, 2017 by Jacques1 Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.