2012-07-11 5 views
5

Ich habe eine Art von Chat/Forum-Anwendung, die nach neuen Nachrichten mit regelmäßigen Abfragen (alle 15 Sekunden) mit jQuery Ajax überprüft. Ich habe mich gefragt, ob ich das Problem von Benutzern lösen kann, die versuchen, "witzig" zu sein, indem sie mehrere gleiche Browser-Instanzen laden, mit vielen Tabs, die alle auf dieselbe Anwendung verweisen. Jede Registerkarte sendet eine Ajax-Anforderung, die möglicherweise einen Server überlaufen kann, wenn mehrere Benutzer dasselbe tun.Wie umgehen Server-Flooding durch Benutzer unzählige Tabs öffnen?

Ich speichern Sitzungen in einer Tabelle zusammen mit der letzten Zugriffszeit und IP-Adresse, die gut funktioniert, solange Benutzer nicht den gleichen Browser verwenden. Ich könnte einen eindeutigen Identifizierer speichern, der mit der ajax POST- oder GET-Anfrage gesendet wird, aber das würde Probleme verursachen, wenn ein normaler (nicht missbräuchlicher) Benutzer seine Seite aktualisiert, was dann einen neuen Identifizierer erzeugen würde.

Das ist noch kein wirkliches Problem, aber fangen Sie es besser, bevor jemand denkt, das System so zu missbrauchen :) Irgendeine Idee, wie man das macht?

+0

Die einzige Sache, die ich denken könnte, dass Sie möglicherweise tun könnte, ist eine Art Begrenzung der Geschwindigkeit (d. H. Begrenzen Sie die Anzahl der Abfragen Anfragen pro Sitzung/Zeitraum). –

+0

Hmm, daran dachte ich noch nicht. Ich habe Einschränkungen, die die Ajax-Abfrage nach 5 Minuten Inaktivität stoppen, aber ich könnte sie etwas erweitern. – Sempiterna

+0

Eigentlich kann das nicht wirklich mit PHP gemacht werden, da dies immer noch eine Ajax-Anfrage erfordert. Ist es möglich, es mit Javascript zu begrenzen? Mit anderen Worten, kennen alle Tabs im selben Browser die Anforderungen des jeweils anderen, und begrenzen sie dies mit javacsript? Gibt es im Grunde einen internen Browser-Zähler, der sieht, dass gerade eine Anfrage in Tab X gemacht wurde, und Code dort drin hat, so dass der Tab Y keine Ajax-Anfragen mehr sendet? – Sempiterna

Antwort

0

Ich habe das ähnliche Problem. Jetzt zwinge ich alle Benutzer, sich einzuloggen (es bedeutet, dass ich ihre E-Mails habe). Auch ich setze Verbindungslimit pro Konto und Anfrage Limit pro Verbindung, nach 5 Überläufen ich frage Benutzer, Captcha eingeben, dann blockiere ich Konto für eine 30 min und senden Sie E-Mail mit Passwort-Recovery-Link. Es ist keine klare Lösung, aber jetzt funktioniert es für mich.

UPD:

Der einfachste Weg, dies zu tun ist Cookie oder Session-Speicherung zu verwenden. Ich benutze Cookies. Der Algorithmus ist einfach:

  1. Benutzeranmeldung im Internet.
  2. Überprüfen Sie, ob eine Sitzung für diesen Benutzer geöffnet ist, geöffnet ist, löschen Sie dann die andere Sitzung oder Auslöser Ausnahme oder wechseln zu dieser Sitzung, Sie haben Ihre eigenen die gewünschte Verhalten.
  3. Erstellen Sie eine Sitzungs-ID für den Benutzer und speichern Sie ihn in der Datenbank.
  4. Erhöhen Sie die Anzahl der Sitzungen Zählerfeld für bestimmte Benutzer, um geöffnete Sitzungen zu erkennen, so dass es jetzt keine Rolle mehr spielt, ob ein Browser verwendet wird oder viele.
  5. Letzte Access-Markierung aktualisieren (ich verwende microtime(true) + $delay und mysql decimal(14,4)). Schicken Sie es an Benutzer
  6. Send-ID Client

Auf jeder Anfrage:

  1. Suche nach Sitzung übergeben ID in $ _COOKIE.
  2. Überprüfen Sie die letzte Zugriffsmarke. Wenn es weniger als microtime(true) bedeutet es, dass Client Anfragen senden zu häufig, so entscheiden Sie selbst, was zu tun ist, erhöhen Sie die Marke, zum Beispiel microtime(true) + $delay + $penalty oder fallen ganze Sitzung oder Fehler auslösen. Das Verhalten hängt von Ihrer Anwendung ab.
+0

Wie bekommen Sie die Anzahl von Verbindungen für einen Benutzer, wenn dieser Benutzer mehrere Male aus demselben Browser verbindet?Ein eindeutiger Identifizierer, der mit jedem POST oder GET gesendet wird? Ein Anforderungslimit wäre nutzlos, da dies immer noch eine Ajax-Anforderung erfordern würde, die an den Server gesendet wird, wo geprüft wird, ob das Limit erreicht ist. – Sempiterna

+0

Siehe aktualisierte Antwort – pinepain

+0

@RikkusRukkus es ist nicht sicher, sich auf localStorage zu verlassen, da seine Daten vom Benutzer geändert werden könnten – pinepain

0

Nicht sicher, ob es in Javascript do-fähig ist. Sie können überprüfen, ob die Registerkarte aktiv ist. Und nur die Ajax auf dem aktiven Tab?

+0

Das könnte eine Idee sein, mit onfocus/onblur oder so etwas zu betrachten. Nicht sicher, ob das in allen Browsern und mobilen Geräten funktioniert, aber es ist einen Test wert. – Sempiterna

2

Eine Option könnte sein, Daten zu holen, wie so:

  • Ihr Skript Daten abzufragen vorbereitet.Bevor Sie die Anforderung ausführen, schreiben Sie (mit LocalStorage) einen Wert, der besagt, dass Sie Daten abrufen werden. localStorage.setItem("last-request-timestamp", new Date().getTime());
  • Abfrage nach Daten. Sie erhalten ein Ergebnis. Schreiben Sie dieses Ergebnis an localStorage: localStorage.setItem("latest-messages", ajax_result);
  • Prüfen Sie, ob eine Seite Daten abfragen möchte, indem Sie prüfen, ob localStorage.getItem("last-request-timestamp") länger als 15 Sekunden zurückliegt. Ist dies der Fall, mit Schritt 1 fortfahren. Wenn nicht, 15 Sekunden warten und erneut prüfen.
  • Unabhängig davon, ob die aktuelle Seite nach Daten abgefragt wird oder nicht, überprüfen Sie die Variable latest-messages und aktualisieren Sie die Seite.

Andere Seiten teilen natürlich die localStorage-Daten. Sie erhalten keine Daten, wenn gerade eine andere Seite abgerufen wird. Wenn Seite 1 geschlossen ist, wird eine der anderen Seiten weiterhin Daten abrufen.

Ich habe LocalStorage noch nicht verwendet, aber die Browserunterstützung scheint anständig genug zu sein. Sie sollten es auch als Schlüssel/Wert-Array verwenden können: localStorage["last-request-timestamp"].

Sie können Zeichenketten nur in localStorage speichern, aber Sie können sie natürlich in JSON serialisieren.

+0

Interessant, ich hatte vorher noch nichts davon gehört. Ich nehme an, dass dies innerhalb der jquery-Codebausteine ​​gesetzt und verwendet werden kann, so dass dies nur für bestimmte Anfragen gilt. Ich werde mir das anschauen, danke :) – Sempiterna

0

Warum nicht etwas wie Memcached/Redis auf das Problem werfen? Cache eine Antwort mit einer Lebensdauer von 10-15s und vermeiden Sie so viel Verarbeitung wie möglich.

Verwandte Themen