Reputation: 15
Hello to this great community,
I have written the following lines of code.
mysql_query("DELETE FROM token_db WHERE date < ".strtotime('-1 day'));
$token = mt_rand(1000, 9999);
$result = mysql_query("SELECT token FROM token_db WHERE token = $token");
while (mysql_num_rows($result) == 1)
{
$token = mt_rand(1000, 9999);
$result = mysql_query("SELECT token FROM token_db WHERE token = $token");
}
mysql_query("INSERT INTO token_db (date,token) VALUES('$date','$token')");
This script generates me tokens which exist max. 24 hours in the database. How can I add the possibilty to extend the token by one digit (e.g. 5-digit) if all tokens (e.g. 4-digit) are in use? THANK YOU!
Upvotes: 1
Views: 546
Reputation: 6490
You need to perform a count on the token db and count token entries.
mysql_query("SELECT count(token) FROM token_db");
If they reach a predefined limit like say 9000 or your 9999 then just
$token = mt_rand(10000, 99999);
But I would rather suggest to increase your token size if you do expect larger numbers to avoid handling of scenarios which are more or less common for your situation.
What is your typical use case? Do you already expect larger sizes?
Anyway your entropy is quite small. With a full database (say 9000 entries) you will have a very hard time finding a valid token. The application would hang, the user would have to wait while your script hammers the database.
If you expect many tokens, you could think about pre-filling the database with tokens without a date. Then you could retrieve a randomized set of tokens (LIMIT 1 or 10) where no date has been set and use this.
You try to achieve scalability by this but I doubt that it will work that well, except you increase the token digit size when your DB has still 50% "space"
Edit: Another problem might be worth mentioning: Do you protect any important resource by such a token system? You have chosen a token which is very small, the token collision has been discussed but what has been left out is the ability of a user to guess a token. If you protect sensitive information by this way and you read the token from an url (e.g. you sent the generated token to the user via mail, etc) than a malicious user may impersonate another by guess a token. This is very likely to occur if you have your 4-digit tokens used up. That's where uniqid and other large entropy algorithms kick in.
Upvotes: 1
Reputation: 16113
Something along these lines I guess:
$result = mysql_query("SELECT count(id) as numRows FROM token_db"); // credit for the edit to Samuel
$fetch = mysql_fetch_assoc($result);
$foundRows = $fetch['numRows'];
$token = $foundRows===(9999-1000) ? mt_rand(10000, 99999) : mt_rand(1000, 9999);
I've added the braces to clarify what is happening, and used 9999-1000 to show you how I got to the number (the max-min of the mt_rand
). If set it to the column id
because those are often index, integers and fast :)
You do the test before the while.
And the usual: Start using mysql*i* functions
An better, more permanent solution would be uniqid()
:
$token = uniqid();
That will always be an unique id (surprise). No need for check that might get complicated and no maximum tokens (at least not for a long while),
Upvotes: 1