7 Stimmen

Mehrere PHP-Skriptaufrufe von mehreren XHR-Instanzen verarbeiten

Zuvor gestylte Frage: http://pastebin.com/cr432nLQ

Ich habe beschlossen, die gesamte Frage zu diesem Problem neu zu formulieren und so gründlich wie möglich vorzugehen. Sie können die zuvor gestellte Frage im obigen Paste lesen.

Zunächst einmal vielen Dank an alle für ihre Antworten, aber leider bin ich nicht weitergekommen. Ich brauche immer noch Hilfe für mein Problem.

Also, ich benutze ein jQuery-Plugin namens blueimp jQuery File Upload, das sich sehr gut um die asynchrone Dateiübertragung kümmert und viele Optionen enthält. Das Plugin funktioniert für meine Zwecke gut genug, aber es gibt diese serverseitige Prüfung, die ich durchführen muss, um mich vor missbräuchlichen Benutzern zu schützen. Ich spreche von der Begrenzung der Anzahl der gleichzeitigen Uploads.

Das Plugin funktioniert standardmäßig so: Der Benutzer wählt eine Anzahl von Dateien aus (oder zieht sie in die Drop-Zone) und jede Datei erstellt eine separate XHR-Instanz, die dann mein upload.php-Skript aufruft, das sich um die Speicherung der Dateien kümmert. Das PHP-Upload-Skript behandelt die XHR-Anfragen, als handele es sich nur um ein Bild, sodass jedes Bild, das hochgeladen werden muss, das upload.php-Skript separat aufruft.

Was ich meinen Benutzern erlaube, hochzuladen, sind Bilder. Allerdings möchte ich einige Grenzen für die Anzahl der Uploads festlegen, nämlich 10 für normale Benutzer und 20 für Premium-Benutzer. Dies ist mit JavaScript möglich, ja, aber ich vertraue JavaScript nicht wirklich für diese Art der Validierung, daher suche ich eine serverseitige Validierung. Aber wie? Dies ist ziemlich unmöglich (zumindest für mich), sicher durchzuführen. Ich muss auf meinem Upload-Skript irgendwie sicherstellen, dass der Benutzer die Grenze von 10 (oder 20) Bilduploads nicht überschritten hat.

Ich habe herausgefunden, dass dieses jQuery-Plugin diese Option namens singleFileUploads hat:

Standardmäßig wird jede Datei einer Auswahl über eine individuelle Anfrage für XHR-Uploads hochgeladen. Legen Sie diese Option auf false fest, um Dateiauswahlen in einer Anfrage hochzuladen.

Hinweis: Das Hochladen mehrerer Dateien mit einer Anfrage erfordert, dass die Option multipart auf true gesetzt ist (standardmäßig).

  • Typ: boolean
  • Standard: true

Dies tut ziemlich genau das, was ich brauche - Es sendet ein vollständig gefülltes $_FILES-Array mit allen eingereichten Bilduploads. Aber ich sehe immer noch ein Problem damit. Dies wird immer noch von JavaScript selbst entschieden. Kann ein Benutzer diesen Teil des Skripts ändern und singleFileUploads erneut auf false setzen? Ich denke, das können sie! Wenn sie das nicht könnten, dann wäre diese Frage jetzt beantwortet - aber ich weiß es nicht.

Es gibt eine Antwort weiter unten, die die Verwendung von Apaches mod_qos vorschlägt, um die Anzahl der Bilduploads zu begrenzen, aber ich habe keine Ahnung, wie man es für die beiden verschiedenen Benutzertypen (normal und Premium) unterschiedlich machen kann.

Bitte beachten Sie, dass auch Gästen das Hochladen von Bildern erlaubt ist und die Grenze für kostenlose Benutzer auch für sie gelten sollte.


Was habe ich bisher in Bezug auf all das versucht?

Ich habe versucht, eine Lösung mit Sitzungen zu erstellen, die verfolgen würden, wie viel der Benutzer hochlädt und bei jedem neuen Upload würde der Wert der Sitzung um eins erhöht werden - eine Lösung, die wie unten vorgeschlagen nicht sicher genug war, da die Cookies gelöscht werden können. Abgesehen von diesem Versuch konnte ich nichts aus den unten stehenden Antworten anwenden.


Die Frage

Nun, die Frage ist seit Beginn ziemlich klar: Wie kann ich die Anzahl der gleichzeitigen Bilduploads auf 10 für Gäste/kostenlose Benutzer und 20 für Premium-Benutzer sicher begrenzen?

BEARBEITEN: Es ist wohl erwähnenswert, dass jedes hochgeladene Bild seine eigene Zeile in der Datenbank mit Zeitpunkt und Namen erhält. Vielleicht kann dies helfen!

Vielen Dank.

0voto

Bryan Waters Punkte 636

Warum also nicht einfach eine fortlaufende Zählung aller Uploads nach IP oder IP / User-Agent (immer noch fälschbar, aber besser als Cookies) beibehalten?

Bevor Sie mit Ihrem Upload beginnen, ruft Ihr Ajax einen Precheck mit der Liste der Dateinamen auf.

Der PHP-Code schreibt einen Datensatz für jede Datei in die Datenbank.

IP / User-Agent / Dateiname oder eindeutige Datei-ID / zuletzt aktualisiert

Sie löschen alle alten Datensätze, die älter als eine Timeout von 30 Minuten oder 2 Tagen sind. (Dies schützt sie, wenn ihr Upload durch eine Netzwerkverbindung unterbrochen wird, usw.)

Dann zählen Sie die Anzahl der Zeilen für diese IP / User-Agent und geben einen Fehler über Ajax zurück. Dies geschieht alles vor dem eigentlichen Upload.

In Ihrem Upload-Code überprüfen Sie, ob die Datei einen Datensatz in der Datenbank hat. Wenn nicht, haben sie den Precheck umgangen (oder Ihr Timeout überschritten) und Sie speichern die Datei nicht ab und geben stattdessen einen Fehler aus. Wenn jedoch ein Datensatz vorhanden ist, speichern Sie die Upload-Datei und löschen den Datensatz.

Sie müssen das Timeout sorgfältig wählen. Wenn die Zeit zum tatsächlichen Hochladen eines Bildes Ihr Timeout überschreitet, werden sie nie in der Lage sein, einen Upload abzuschließen. Wenn ihr Upload schnell abbricht, dh ihre Internetverbindung abbricht, können sie den Precheck nicht bestehen, bis die Timeout-Periode abläuft.

Wie an anderer Stelle erwähnt, wird PHP erst ausgeführt, nachdem der Upload bereits mit Ihrem Webserver abgeschlossen wurde. So entziehen Sie nur den Vorteil des gleichzeitigen Ausführens mehrerer Uploads in verschiedenen Tabs usw. Sie schützen sich nicht vor einer Art von DoS-Angriff. Dafür benötigen Sie eine Apache-Rate-Limit-Erweiterung oder verwenden IPTABLE-Regeln.

0voto

Sharad D Punkte 329

Ich hatte ein ähnliches Problem, bei dem ich den Gesamtfestplattenspeicher begrenzen wollte, den jeder Benutzer hochlädt. (Ich hatte eine eindeutige ID für den Benutzer in der Datenbank, Sie können die IP verwenden). Hier sind die Dinge, die ich gemacht habe

  1. Als die Seite geladen wurde, habe ich einen Hash aus zufälligem String (Salz + Zeit) erstellt und in der Sitzung gespeichert.
  2. Als Datei/Dateien hochgeladen wurden, musste der gleiche Hash per POST gesendet werden. Bei einem Missmatch wird der Upload abgelehnt. Nach erfolgreichem Datei-Upload wurde der zufällige String geändert. Daher können neue Dateien aus demselben Formular hochgeladen werden, ohne dass die Seite neu geladen werden muss.
  3. Nach dem Upload würde ich eine ini-Datei pro Benutzer(pro IP) führen, die Aufzeichnungen über die Anzahl der hochgeladenen Dateien und die Dateigröße enthielt. Ich würde die Datei ablehnen, wenn die Grenzen erreicht sind. In diesem Fall bevorzugte ich die Datei, da ich keine zentrale Datenbank zum Analysieren benötigte. Außerdem mussten keine Indexe/Suchanfragen/beziehungsweise die Datenbank ordnen. Wenn Sie eine Datenbank verwenden möchten, würde ich separate sqlite-Datenbanken pro Benutzer/IP für schnellere Abfragen vorschlagen.

Die IP ist zuverlässiger, da der User-Agent gefälscht werden kann und Cookies gelöscht werden können (und damit die Sitzungs-ID des Browsers). Selbst die IP kann zurückgesetzt werden, wenn Sie eine dynamische IP haben. Wenn Sie zu viele Anfragen erhalten und glauben, dass Sie angegriffen werden, können Sie vorübergehend alle Uploads deaktivieren.

0voto

PRAISER Punkte 793

Ich würde vorschlagen, dass du tun kannst, was du willst, aber wenn der Upload beendet ist, sende einfach das Ergebnis zurück mit einer Überprüfung des Status des Benutzers, der den Upload angefordert hat, und genau dort kannst du die Sitzung löschen, wenn der Benutzer existiert/nicht existiert. Sie werden das Ergebnis nicht erhalten, wenn sie ihre IP-Adresse oder Sitzungsschlüssel ändern.

Du kannst einen einfachen Schlüssel in der Datenbank/Sitzung halten, um das Ergebnis an den richtigen Benutzer zu liefern.

0voto

Itay Gal Punkte 10331

Wie ich verstehe, möchten Sie verhindern, dass ein Benutzer innerhalb eines Zeitraums zu viele Dateien hochlädt. Um dies tatsächlich zu tun, müssen Sie den Benutzer auf der Serverseite identifizieren (unter der Annahme, dass jede Clientseite manipuliert werden kann), ohne eine Registrierung. Ich fürchte, das ist nicht möglich.

Aber Sie haben 2 ziemlich gute Möglichkeiten:

  1. Identifizieren Sie den Benutzer mit Clientseite, Cookies, Sitzungen, IP, Benutzer-Agent oder anderen Faktoren und/oder Kombinationen davon, so dass ein bösartiger Benutzer hart arbeiten muss, um Ihre Systemlöcher auszunutzen. Es ist nicht perfekt, aber es wird die meisten Versuche durchschnittlicher Benutzer verhindern.

  2. Verwenden Sie ein serverseitiges Authentifizierungssystem. Sie haben erwähnt, dass Sie keinen Traffic verlieren möchten, aber wenn Ihre kostenlosen Benutzer nicht einmal eine Minute für die Registrierung (nur E-Mail und Passwort) aufwenden, werden sie wahrscheinlich keine zahlenden Kunden in der Zukunft sein, und somit kann es eine gute Sache sein, "Leerer" Traffic zu verlieren, wenn Sie Traffic-Kosten sparen möchten.

0voto

alpham8 Punkte 1276

Ja, du kannst das auf der Serverseite behandeln. Sitzungen sind sicher. Deaktiviere einfach im PHP-Konfiguration das Session-Cookie. So wird die Session-ID stattdessen zur URL hinzugefügt und nicht in einem Cookie gespeichert. Es gibt also keine Möglichkeit, etwas zu manipulieren.

ABER: Das Handhaben von zu vielen Dateien, die bereits auf dem Server hochgeladen wurden, verursacht unnötigen Datenverkehr im Internet. Deshalb empfehle ich Ihnen dringend zu überprüfen, ob der Benutzer auf der Clientseite weniger als 10 Dateien ausgewählt hat. Sie können dies ganz einfach mit JavaScript machen. Behandeln Sie einfach die Antwort, die der FileChooser-Dialog zurückgibt (auf die gleiche Weise, wie Java es mit seinem JFileChooser macht). In dieser Antwort sollte der String enthalten sein, der alle ausgewählten Dateien in dieser Form enthält:

"pic1.png", "pic2.jpg", "pic3.jpg"

Also, alles, was Sie tun müssen, ist die Anzahl der Dateinamen in diesem String zu zählen. Teilen Sie ihn einfach am , -Zeichen auf und entfernen Sie die " am Anfang und am Ende (Unterzeichen) und legen Sie Ihre Ergebnisse in ein Array. Zählen Sie die Länge des Arrays. Wenn die Länge größer als 10 ist => der Benutzer hat zu viele Dateien ausgewählt.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X