Reputation: 47
Anyone can use a simple for loop on a ajax chat, and make the chat send 1000 messages at times. In my ajax chat, every message gets stored with date, time (timestamps).
I need to find out a way to prevent this problem, I have thought on one, but I am not sure how would I do it:
Prevent spam by post time
Basically selecting 5 messages that their date, time showing less than 10 seconds old (together). If these messages, together been posted in less than 10 seconds, block the user from the chat for a few seconds.
But I don't really think this can work, nor know how to do this.
Are there any similar, or better solutions, or tips on how to?
Upvotes: 1
Views: 1565
Reputation: 592
You want to control that on the server side as, as mentioned in the other comments, your spammers might know enough JavaScript to remove any protection.
Using PHP and MySQL, here is a suggestion:
// check if the user is spamming
$r_antispam = mysqli_query($db, "SELECT `date` FROM `the_messages` WHERE `id_conversation`=111 AND `id_exp`=222 AND `date` >= DATE_SUB(NOW(), INTERVAL 10 SECOND) LIMIT 8");
if(mysqli_num_rows($r_antispam) == 8)
{ echo 'spam'; exit(); }
Of course, you might want to adjust the delay and maximum number of messages you allow within it.
Now in your Ajax request, you can use the word "spam" returned by the Ajax file this way:
$.post("ajax/messages-post.php", {
id_conv: 111,
message: message_text
}).
done(function(e)
{
if(e == 'spam')
{
alert('do not spam, please...');
}
else
{
// your message is posted, you can display it
}
}).
fail(function() { console.log('error'); });
In your JavaScript, if you empty the textarea where your users write their messages before you post its value to the Ajax file, because the message won't be recorded in the database, you can reinsert it inside the textarea just in case it wasn't a spam...
Upvotes: 0
Reputation: 32260
In the part of your scripts, where the server is about to save the chat message, you hook up a database query like
SELECT COUNT(*)
FROM chat_messages
WHERE uid='1234' AND timestamp > DATE_SUB(NOW(), INTERVAL 10 SECOND)
LIMIT 10
then check if the result is greater than your limit and return false, or a message "too many messages sent in too short time"
Another, maybe better approach would be to identify not only a user/session, but also save the IP and limit messages to an IP. Many modern bots can easily circumvent sessions or switch IP very fast, so you should go for a combination of more than one technics.
Also consider client side prevention, like hashing the message, or adding a checksum to the messages. Many bots don't talk JavaScript too good.
Upvotes: 3
Reputation: 16103
EDIT: the solution posted by DanFromGermany is a good method if you have database resource to spare. If the DB is a bottleneck, you can switch to the following method:
You have an AJAX call to a phpfile, let say process.php. In process.php you start a session, and start a value $_SESSION['lastChatMessage']=0;
Then you make an if/else arround the actual code:
// time based check:
if($_SESSION['lastChatMessage'] > time()-1 ){ echo "Only one post per second";}
else{
// some code you use now
$_SESSION['lastChatMessage'] = time();// save time of posting
}
You could also make an array of $lastChatMessage and remember each time in it. Then make a function which deletes all values smaller than time()-$diffYouWant. A number of posts will remain, it's up to you how large you want that number to be :)
if(count( $_SESSION['lastChatMessage']) > $maxPostsAllowed){ echo 'No flooding please';}
else{
// your code
}
Upvotes: 5