2012-07-16 14 views
9

Udostępniam usługę internetową dla moich klientów, która pozwala mu dodać rekord do produkcyjnej bazy danych.Zapobiegaj nawiązywaniu połączeń z serwisem zbyt wiele razy

Ostatnio miałem incydent, w którym programista mojego klienta nazwał usługę w pętli, iterował, aby zadzwonić do mojej usługi tysiące razy.

Moje pytanie brzmi, jaki byłby najlepszy sposób, aby temu zapobiec.

Pomyślałem o kilku sposobach: 1. Przy wejściu do usługi mogę zaktualizować liczniki dla każdego klienta, który wywołuje usługę, ale to wygląda zbyt niezdarnie. 2.Sprawdź adres IP klienta, który wywołał tę usługę, i podnieś flagę za każdym razem, gdy wywoła usługę, a następnie zresetuj flagę co godzinę.

Jestem przekonany, że istnieją lepsze sposoby i można by zastosować wszelkie sugestie.

Dzięki, David

+0

innym pomysłem, Aktualizowanie sesji tego użytkownika: –

+0

przypuszczam masz jakieś "luzem "dodać metodę? – Phil

+0

Tak, jest ... –

Odpowiedz

3

Droga jest przechowywanie na sesji licznik i korzystać z licznika, aby zapobiec zbyt wiele połączeń na raz.

Ale jeśli użytkownik może spróbować tego uniknąć i wysłać za każdym razem inny plik cookie *, musisz utworzyć niestandardową tabelę, która będzie działać tak samo jak sesja, ale połączyć użytkownika z adresem IP, a nie z plikiem cookie.

Jedną z nich jest to, że jeśli zablokujesz podstawowe ustawienia IP, możesz zablokować całą firmę, która wychodzi z serwera proxy. Ostatecznym, poprawnym sposobem, ale bardziej skomplikowanym, jest posiadanie zarówno adresu IP jak i pliku cookie połączonego z użytkownikiem i sprawdzanie, czy przeglądarka zezwala na cookie, czy nie. Jeśli nie, to blokujesz przy pomocy ip. Trudną częścią jest wiedzieć o cookie. Cóż za każde połączenie można zmusić go do wysłania ważnego pliku cookie, który jest połączony z istniejącą sesją. Jeśli nie, przeglądarka nie ma plików cookie.

[*] Pliki cookie są powiązane z sesją.
[*] Wykonując nową tabelę, aby zachować liczniki i rozłączyć się z sesją, można również uniknąć blokady sesji.

W przeszłości używam kodu, który był używany dla DosAttack, ale żaden z nich nie działa dobrze, gdy masz wiele basenów i trudną aplikację, więc teraz używam niestandardowej tabeli, jak to opisuję. To są dwa, że ​​kod mam test i używać

Dos attacks in your web app

Block Dos attacks easily on asp.net

Jak znaleźć kliknięć na sekundę zapisanych na stole. Oto część mojego SQL, która oblicza liczbę kliknięć na sekundę. Jedną z tych sztuczek jest to, że nadal dodajemy kliknięcia i obliczam średnią, jeśli mam 6 lub więcej sekund od ostatniego sprawdzenia. Jest to kod wycięte z obliczeń jako 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 [email protected]   
ELSE IF @cMilSecDif > 16000 
    UPDATE ATMP_LiveUserInfo SET cDos_TotalCalls = (cDos_TotalCalls/2), 
    cDos_TotalCallsChecksOn = DATEADD(millisecond, @cMilSecDif/2, cDos_TotalCallsChecksOn) 
     WHERE [email protected] 
+0

Dzięki za odpowiedź, Powiedzmy, że aktualizuję sesję: Session ["ServiceInvoked"] = true; i zapytaj, czy zapytamy na początku sesji: jeśli ((bool) Session ["ServiceInvoked"]) ... uniemożliwi to połączenie. ALE, jak mógłbym je zresetować po, powiedzmy, godzinie? –

+0

Jeśli wstawię Datetime, mogę pracować, ponieważ mogę sprawdzić Session Datetime Subscract DateTime.Now, i zezwalać na wywołanie usługi .... –

+0

@ DavidRasuli Używasz pola DateTime z ostatniej aktualizacji wraz z licznik i wykonujesz średnie obliczenia - widzisz na przykład w ostatnim Dniu, że ostatnie pytanie było przed 1 sekundą, a wszystkie gotowe mają 10 połączeń. Innymi słowy przerwałeś go na ostatnie telefony, nie na teraz. – Aristos

3

najpierw trzeba spojrzeć na prawnych aspektów sytuacji: Czy umowa z klientem pozwalają ograniczyć dostęp klienta?

To pytanie jest poza zakresem zgłoszenia zastrzeżeń, ale musisz znaleźć sposób, aby na nie odpowiedzieć. Ponieważ jeśli jesteś prawnie zobowiązany do przetworzenia wszystkich wniosków, nie ma możliwości obejścia tego.Analiza prawna Twojej sytuacji może już zawierać pewne ograniczenia, w związku z czym możesz ograniczyć dostęp. To z kolei będzie miało wpływ na twoje rozwiązanie.

Pomijając wszystkie te problemy i koncentrując się na aspektach związanych z , czy korzystasz z pewnego rodzaju uwierzytelniania użytkownika? (Jeśli nie, to dlaczego?) Jeśli tak, możesz zaimplementować dowolny schemat, który zdecydujesz się użyć dla jednej bazy użytkowników, co moim zdaniem byłoby najczystszym rozwiązaniem (nie musisz polegać na adresach IP, które są w jakiś sposób brzydki sposób obejścia).

Po zidentyfikowaniu pojedynczego użytkownika można wprowadzić kilka ograniczeń. Pięść te, które przychodzą mi do głowy, są takie:

  1. synchroniczne przetwarzanie
    Tylko rozpocząć przetwarzanie żądania po wszystkie wcześniejsze wnioski zostały przetworzone. Może to być nawet zaimplementowane przy użyciu tylko głównej instrukcji przetwarzania. Jeśli zdecydujesz się na tego rodzaju podejście, opóźnienie czasowe między żądaniami przetwarzania
    Wymaga, aby po jednym wywołaniu przetwarzania upłynął określony czas, zanim będzie możliwe następne wywołanie. Najłatwiejszym rozwiązaniem jest zapisanie znacznika czasu LastProcessed w sesji użytkownika. Jeśli zdecydujesz się na takie podejście, musisz zacząć zastanawiać się, jak zareagować, gdy pojawi się nowe żądanie, zanim zostanie ono przetworzone. Czy wysyłasz komunikat o błędzie do dzwoniącego? Myślę, że powinniśmy ...

EDIT
Oświadczenie lock, krótko wyjaśnił:

Jest on przeznaczony do stosowania bezpiecznych operacji gwintów. składnia jest następująca:

lock(lockObject) 
{ 
    // do stuff 
} 

W lockObject musi być przedmiot, zwykle prywatny członkiem bieżącej klasy. Efekt jest taki, że jeśli masz 2 wątki, które chcą wykonać ten kod, pierwszy, który otrzyma instrukcję lock, zablokuje lockObject. Chociaż robi to rzeczy, drugi wątek nie może uzyskać blokady, ponieważ obiekt jest już zablokowany. Więc po prostu siedzi tam i czeka, aż pierwszy wątek zwolni blokadę, gdy wyjdzie z bloku na }. Tylko wtedy drugi wątek może zablokować lockObject i zrobić to, blokując lockObject dla każdego trzeciego wątku, dopóki nie opuści również bloku.

Ostrożnie, cała kwestia bezpieczeństwa nici nie jest banalna. (Można powiedzieć, że jedyną rzeczą, która jest trywialna jest wiele drobnych błędów, jakie może popełnić programista ;-) See here Wprowadzenie do wątków w C#

+0

Świetna odpowiedź Treb, czy mógłbyś bardziej szczegółowo opisać stwierdzenie "blokada", ponieważ nie jestem mu obeznany? –

+1

@David: 'lock' jest udokumentowane tutaj http://msdn.microsoft.com/en-us/library/c5kehkcz(v=vs.100).aspx – Grhm

0

Uzyskaj adres IP użytkownika i wstaw go do pamięci podręcznej przez godzinę po skorzystaniu z sieci usługa ta jest buforowane na serwerze:

HttpContext.Current.Cache.Insert("UserIp", true, null,DateTime.Now.AddHours(1),System.Web.Caching.Cache.NoSlidingExpiration); 

Kiedy trzeba sprawdzić, czy użytkownik wszedł w ostatniej godzinie:

if(HttpContext.Current.Cache["UserIp"] != null) 
{ 
//means user entered in last hour 
} 
Powiązane problemy