Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Prevent calling a web service too many times

I provide a Web Service for my clients which allow him to add a record to the production database.

I had an incident lately, in which my client's programmer called the service in a loop , iterated to call to my service thousands of times.

My question is what would be the best way to prevent such a thing.

I thought of some ways: 1.At the entrence to the service, I can update counters for each client that call the service, but that looks too clumbsy. 2.Check the IP of the client who called this service, and raise a flag each time he/she calls the service, and then reset the flag every hour.

I'm positive that there are better ways and would appriciate any suggestions.

Thanks, David

like image 507
David Rasuli Avatar asked Jul 16 '12 07:07

David Rasuli


2 Answers

The way is to store on the session a counter and use the counter to prevent too many calls per time.

But if your user may try to avoid that and send different cookie each time*, then you need to make a custom table that act like the session but connect the user with the ip, and not with the cookie.

One more here is that if you block basic on the ip you may block an entire company that come out of a proxy. So the final correct way but more complicate is to have both ip and cookie connected with the user and know if the browser allow cookie or not. If not then you block with the ip. The difficult part here is to know about the cookie. Well on every call you can force him to send a valid cookie that is connected with an existing session. If not then the browser did not have cookies.

[ * ] The cookies are connected with the session.
[ * ] By making new table to keep the counters and disconnected from session you can also avoid the session lock.

In the past I have use a code that used for DosAttack, but none of them are working good when you have many pools and difficult application so I now use a custom table as I describe it. This are the two code that I have test and use

Dos attacks in your web app

Block Dos attacks easily on asp.net

How to find the clicks per seconds saved on a table. Here is the part of my SQL that calculate the Clicks Per Second. One of the tricks is that I continue to add clicks and make the calculation of the average if I have 6 or more seconds from the last one check. This is a code snipped from the calculation as an idea

set @cDos_TotalCalls = @cDos_TotalCalls + @NewCallsCounter

SET @cMilSecDif = ABS(DATEDIFF(millisecond, @FirstDate, @UtpNow))

-- I left 6sec diferent to make the calculation
IF @cMilSecDif > 6000
    SET @cClickPerSeconds = (@cDos_TotalCalls * 1000 / @cMilSecDif)
else
    SET @cClickPerSeconds = 0

IF @cMilSecDif > 30000
    UPDATE ATMP_LiveUserInfo SET cDos_TotalCalls = @NewCallsCounter, cDos_TotalCallsChecksOn = @UtpNow WHERE cLiveUsersID=@cLiveUsersID         
ELSE IF @cMilSecDif > 16000
    UPDATE ATMP_LiveUserInfo SET cDos_TotalCalls = (cDos_TotalCalls / 2), 
    cDos_TotalCallsChecksOn = DATEADD(millisecond, @cMilSecDif / 2, cDos_TotalCallsChecksOn)
        WHERE cLiveUsersID=@cLiveUsersID
like image 144
Aristos Avatar answered Oct 22 '22 16:10

Aristos


First you need to have a look at the legal aspects of your situation: Does the contract with your client allow you to restrict the client's access?

This question is out of the scope of SO, but you must find a way to answer it. Because if you are legally bound to process all requests, then there is no way around it. Also, the legal analysis of your situation may already include some limitations, in which way you may restrict the access. That in turn will have an impact on your solution.

All those issues aside, and just focussing on the technical aspects, do you use some sort of user authentication? (If not, why not?) If you do, you can implement whatever scheme you decide to use on a per user base, which I think would be the cleanest solution (you don't need to rely on IP addresses, which is a somehow ugly workaround).

Once you have your way of identifying a single user, you can implement several restrictions. The fist ones that come to my mind are these:

  1. Synchronous processing
    Only start processing a request after all previous requests have been processed. This may even be implemented with nothing more but a lock statement in your main processing method. If you go for this kind of approach,
  2. Time delay between processing requests
    Requires that after one processing call a specific time must pass before the next call is allowed. The easiest solution is to store a LastProcessed timestamp in the user's session. If you go for this approach, you need to start thinking of how to respond when a new request comes in before it is allowed to be processed - do you send an error message to the caller? I think you should...

EDIT
The lock statement, briefly explained:

It is intended to be used for thread safe operations. the syntax is as follows:

lock(lockObject)
{
    // do stuff
}

The lockObject needs to be an object, usually a private member of the current class. The effect is that if you have 2 threads who both want to execute this code, the first to arrive at the lock statement locks the lockObject. While it does it's stuff, the second thread can not acquire a lock, since the object is already locked. So it just sits there and waits until the first thread releases the lock when it exits the block at the }. Only thhen can the second thread lock the lockObject and do it's stuff, blocking the lockObject for any third thread coming along, until it has exited the block as well.

Careful, the whole issue of thread safety is far from trivial. (One could say that the only thing trivial about it are the many trivial errors a programmer can make ;-) See here for an introduction into threading in C#

like image 37
Treb Avatar answered Oct 22 '22 16:10

Treb