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> Link to comment Share on other sites More sharing options...
requinix Posted May 2, 2017 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. 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. 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. 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. 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 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. 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. 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. Link to comment Share on other sites More sharing options...
Jacques1 Posted May 2, 2017 Share Posted May 2, 2017 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)); } Link to comment Share on other sites More sharing options...
Recommended Posts
Archived
This topic is now archived and is closed to further replies.