[ACCEPTED]-Most reliable & safe method of preventing race conditions in PHP-concurrency
In fact, i think there is no need for a 16 complex mutex / semaphore whatever solution.
Form 15 keys stored in a PHP $_SESSION
are all you need. As 14 a nice side effect, this method also protects 13 your form against CSRF attacks.
In PHP, sessions 12 are locked and session_start()
waits until the user session 11 is released. You just have to unset()
the form 10 key on the first valid request. The second 9 request has to wait until the first one 8 releases the session.
However, when running 7 in a (not session or source ip based) load 6 balancing scenario things are getting more 5 complicated. For such a scenario, i'm sure 4 you will find a valuable solution in this 3 great paper: http://thwartedefforts.org/2006/11/11/race-conditions-with-ajax-and-php-sessions/
I reproduced your use case 2 with the following demonstration. just throw 1 this file onto your webserver and test it:
<?php
session_start();
if (isset($_REQUEST['do_stuff'])) {
// do stuff
if ($_REQUEST['uniquehash'] == $_SESSION['uniquehash']) {
echo "valid, doing stuff now ... "; flush();
// delete formkey from session
unset($_SESSION['uniquehash']);
// release session early - after committing the session data is read-only
session_write_close();
sleep(20);
echo "stuff done!";
}
else {
echo "nope, {$_REQUEST['uniquehash']} is invalid.";
}
}
else {
// show form with formkey
$_SESSION['uniquehash'] = md5("foo".microtime().rand(1,999999));
?>
<html>
<head><title>session race condition example</title></head>
<body>
<form method="POST">
<input type="hidden" name="PHPSESSID" value="<?=session_id()?>">
<input type="text" name="uniquehash"
value="<?= $_SESSION['uniquehash'] ?>">
<input type="submit" name="do_stuff" value="Do stuff!">
</form>
</body>
</html>
<?php } ?>
An interesting question you have but you 13 don't have any data or code to show.
For 12 80% of cases the chances of anything nasty 11 happening because of PHP itself are virtually 10 zero if you follow the standard procedures 9 and practices regarding stopping users from 8 submitting forms multiple times, which applies 7 to nearly every other setup, not just PHP.
If 6 you're the 20% and your environment demands 5 it, then one option is using message queues 4 which I'm sure you are familiar with. Again, this 3 idea is language agnostic. Nothing to do 2 with languages. Its all about how data moves 1 around.
you can store a random hash in an array 8 within your session data as well as print 7 that hash as a hidden form input value. when 6 a request comes in, if the hidden hash value 5 exists in your session array, you can delete 4 the hash from the session and process the 3 form, otherwise don't.
this should prevent 2 duplicate form submits as well as help prevent 1 csrf attacks.
If the problem only arises when hitting 5 a button milliseconds apart, wouldn't a 4 software debouncer work? Like saving the 3 time of a button press in a session variable 2 and not allowing any more for, say, a second? Just 1 a before-my-morning-coffee idea. Cheers.
What I do in order to prevent session race 9 condition in the code is after the last 8 operation that stores data in session I 7 use PHP function session_write_close() notice that if you are 6 using PHP 7 you need to disable default 5 output buffering in php.ini. If you have 4 time consuming operations it'd be better 3 to execute them after session_write_close() is 2 invoked.
I hope it'll help someone, for 1 me it saved my life :)
More Related questions
We use cookies to improve the performance of the site. By staying on our site, you agree to the terms of use of cookies.