65.9K
CodeProject is changing. Read more.
Home

Use a floodgate class to block multiple posts

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.58/5 (6 votes)

Sep 27, 2005

CPOL

2 min read

viewsIcon

56676

downloadIcon

231

A simple class to block repeated attempts to submit comments or logins.

Introduction

Here's something that I'd like to share with you. I was developing a website and wanted to limit the number of operations per second that a client is allowed to post. For example, if a visitor posts a comment within 10 seconds of his previous post, it's very unlikely that the post contributed by the person is something useful. Most probably, that post was somehow automated.

Solution

The class that I have written is actually very simple to use. For example if you have an event handler that implements the post of a comment, your code may look something like this:

private void Submit_click(object sender, EventArgs args)
{
    if(Page.IsValid)
    {
        //Your code to persist the details in the database.

    }
}

Now, to add our flood gate, change the code so that it looks something like this:

private static FloodGate _submitFlooding;

private void Submit_click(object sender, EventArgs args)
{
    if(Page.IsValid)
    {
         if(_submitFlooding == null)
    {
         _submitFlooding = new FloodGate("Post Comment", 
                                    TimeSpan.FromSeconds(10))
    }
     _submitFlooding.Assert();
 
    //Your code to persist the details in the database.

    }
}

First, I declare a static reference to a FloodGate class. This makes sure that my floodgate is kept in memory across all the requests that are made to this application.

When somebody clicks on the Submit button, an instance of a FloodGate is assigned. It takes two parameters: the name of the gate, and the minimum delay between each operation.

Whenever somebody (with a certain client IP address) clicks the button within 10 seconds, a FloodGateException is thrown, thereby effectively aborting the operation.

To make it more user friendly, you can catch the exception and show a message box.

The code

It works as follows:

  1. The class maintains a Hashtable of client IP's.
  2. Whenever the Assert() method is called, a check is performed to see if the current client IP (by using HttpContext.Current.Request.UserHostAddress) is already on the list.
  3. If it is, the Hashtable entries contain the DateTime of the last operation. If that date is no longer than n seconds apart (configured by the constructor), a FloodGateException is thrown.
  4. If it isn't (or sufficient time has elapsed), the Hashtable is updated.

If you're interested in seeing the entire code, it is available for download at the top of the page.

The cool thing about this solution is that it is easily reusable in both code-behind and business classes, and that you can declare multiple floodgates for different operations. One of the downsides is that a reference to System.Web is required.

Improvements

The first thing that comes to mind: Clean up IP addresses that have dates older than the minimum waiting time. This will save precious memory.