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.

3voto

LeGEC Punkte 35152

Von Ihrem Kommentar verstehe ich Ihre Frage so: "Ich möchte die Anzahl der gleichzeitigen Upload-Verbindungen pro Client begrenzen (sagen wir: maximal 10 gleichzeitige Uploads pro Client)"

Zunächst einmal: Ich habe mir Ihr JavaScript-Plugin nicht im Detail angesehen, aber ich denke, es erlaubt das bereits. Es sollte mindestens eine Option geben, um die Anzahl der gleichzeitigen Anfragen zu begrenzen.
[Bearbeitet] gefunden: limitconcurrentuploads [/edit]

Allgemeiner: PHP ist nicht das richtige Werkzeug für den Job. Auf der Serverseite wird der Dateiupload (d. h. der Vorgang des Empfangens von Daten über eine HTTP-Verbindung und deren Speicherung in einer Datei auf dem Laufwerk des Servers) von Apache (oder Nginx oder was auch immer) bevor das PHP-Skript aufgerufen wird. Wenn Ihr PHP-Skript startet, ist die Datei bereits hochgeladen, Sie können den Transfer nicht von Ihrem Skript aus unterbrechen.

Auf der Serverseite sollten Sie Ihre php.ini / httpd.conf-Optionen oder Ihr apache / .htaccess-Setup überprüfen. php.ini bietet einige Optionen bezüglich Dateiuploads (Dokumentation).

Am besten schreiben Sie diese Beschränkung in JavaScript auf der Clientseite.

Wenn Sie wirklich Ihr Server absichern wollen, sollten Sie studieren, wie Sie Ihren Apache-Server konfigurieren können, um die Anzahl der gleichzeitigen Verbindungen von derselben IP zu einer bestimmten URL zu begrenzen (ich habe jedoch keinen schnellen, Standardweg gefunden, um das zu tun).


Zum letzten Teil: Ich habe diese Fragen auf ServerFault gefunden

Apache2: Limitierte gleichzeitige Anfragen & Drosselung der Bandbreite pro IP/Client? (2011)
URL-basierte Anfrageratenbegrenzung in Apache (2011)

Die akzeptierte Antwort auf die erste Frage verweist auf das folgende Apache-Modul:
mod_qos

Ich habe es jedoch nicht ausprobiert.

2voto

Lud Punkte 482

Sie könnten einen Aktivierungscode (d.h. eine Zufallszahl) erstellen, wenn Sie die Host-Seite (die Seite, die die xhr-Aufrufe ausgibt) generieren und ihn als Variable innerhalb der Seite an das Skript übergeben. Dann können Sie Ihr JS-Skript so ändern, dass es den Aktivierungscode als GET-Parameter an das Skript übergibt, das den Datei-Upload bearbeitet. Auf diese Weise können Sie den Aktivierungscode als Schlüssel einer Datenbanktabelle verwenden, um die Anzahl der mit diesem Code ausgeführten Uploads zu speichern und zu verfolgen.

Beachten Sie, dass fast alles über HTTP/TCP manipuliert werden kann (nicht nur Sitzungen), also sollten Sie sich nur fragen, was ein Angreifer erreichen kann, wenn er/sie es schafft, Ihr Protokoll auszunutzen.

Sie haben nicht viel über den Kontext dieser Frage geschrieben, aber wenn es um die Ausnutzung von Ressourcen geht, könnten Sie Ihre Benutzer auffordern, ein Konto bei Ihrem Dienst zu eröffnen und ein stündliches/tägliches/wöchentliches Maximum an hochgeladenen GBs für jedes Konto festzulegen.

Hoffe, das hilft.

PS. Sind Sie sicher, dass Sie wirklich die Anzahl der Uploads pro Upload-Sitzung begrenzen müssen? Da jeder Upload separat mit einem separaten Aufruf des Upload-Skripts behandelt wird, denke ich, dass es sicher wäre, dem Benutzer zu erlauben, so viele Bilder hochzuladen, wie er möchte.

0voto

emsoff Punkte 1585

Vielleicht verstehe ich dein Ziel nicht, aber könntest du einfach die Session-Variable einer anderen zuweisen, die Session-Variable vor jeder Schleife zurücksetzen und einen Vergleich anstellen, indem du die Summe der $_SESSION-Anzahl und der "vorherigen" Anzahl verwendest? Versuchst du zu verhindern, dass jeder Benutzer mehr als 10 Gesamtuploads macht, oder verhinderst du nur 10 aufeinanderfolgende Uploads auf einmal?

// Bevor du deine Schleife startest, weise deine Session-Variable einer anderen Variable zu.
$zuvor_hochgeladen = $_SESSION['images_session_uploaded'];

// Setze $_SESSION['images_session_uploaded'] beim Start zurück
$_SESSION['images_session_uploaded'] = 0;

// ... Mach dein Ding.

// Vergleiche am Ende jeder Schleife, was auch immer du überprüfen möchtest.
if (($_SESSION['images_session_uploaded'] + $zuvor_hochgeladen) >= MAX_FREEUSER_UPLOADS_SESSION)
{
  // Der Benutzer hat mehr als zehn Bilder insgesamt hochgeladen, aber nicht unbedingt mehr als zehn in dieser Runde von Uploads.
}

0voto

Pez Cuckow Punkte 13562

Zunächst schützt dich die Verwendung von Sitzungen vor dem durchschnittlichen Benutzer, aber wenn jemand weiß, was er tut, könnte er einfach seine Cookies löschen und so weit wie dein Server es sagen kann, sind sie ein neuer Benutzer.

Vielleicht könnten Sie jeden Benutzer eindeutig identifizieren, entweder indem Sie sie zum Einloggen auffordern oder ihre IP-Adresse oder Browsersignatur verfolgen? Es hängt von deiner Anwendung ab.

Das Hauptproblem hier scheint die Verwendung des undefinierten Ausdrucks Upload-Sitzung zu sein. Was ist eine Upload-Sitzung? Hier gehe ich davon aus, dass es sich um einen Zeitraum von 30 Minuten handelt. Deshalb beschränken wir sie auf 10 Uploads alle halbe Stunde.

Lösung mit Sitzungen:

// Sessions starten, bevor du sie verwenden kannst
session_start();

// "Konfiguration"
$_MAX_UPLOAD_COUNT = MAX_FREEUSER_UPLOADS_SESSION; // Begrenzung für jeden Sitzungstimeout
$_SESSION_TIMEOUT = 60 * 30; // 30 Minuten

// Aktuelle Anzahl der Uploads (Standardmäßig auf null)
$total_uploads_so_far = isset($_SESSION['total_uploads']) ? $_SESSION['total_uploads'] : 0;

// --- Zähle ihre Uploads dieser Sitzung ---
// #1 Entweder durch Schleife durch die Uploads
$uploaded_image += 1;

// #2 Oder vor der Handhabung des Uploads, indem du die Anzahl der hochgeladenen Dateien zählst
$uploaded_images = count($_FILES['images']);

// Sie haben ihre Uploads sofort erschöpft
if($uploaded_images > $_MAX_UPLOAD_COUNT) {
  // Fehlermeldung anzeigen, dass du nicht mehr als 10 Bilder auf einmal auswählen kannst
  // Keine Bilder hochladen oder Sitzungen modifizieren
}

// --- Überprüfe vor Abschluss des Uploads, ob sie nicht mehr als 10 Artikel hochgeladen haben ---

// Haben sie bereits hochgeladen, war es in den letzten 30 Minuten?
$uploaded_recently = isset($_SESSION['last_upload']) && ($_SESSION['last_upload'] + $_SESSION_TIMEOUT) > time();

if($uploaded_recently && ($total_uploads_so_far + $uploaded_images) > $_MAX_UPLOAD_COUNT) {
  // Fehlgeschlagener Upload, Fehlermeldung usw.

} else {
  // Verarbeite deinen Upload

  // Aktualisiere die Informationen in der Benutzersession
  $_SESSION['last_upload') = time();
  $_SESSION['total_uploads') = $uploaded_images + $total_uploads_so_far;

}

Lösung mit IP/Signatur:

Mache dasselbe wie oben, aber speichere anstelle der Speicherung der letzten Upload-Zeit und der Gesamtzahl der Uploads in der Benutzer$_SESSION lege sie in einer Datenbank oder einer Textdatei ab.

Setze den Schlüssel als ihre IP-Adresse (von $_SERVER['REMOTE_ADDR']) oder etwas anderes, um sie eindeutig zu identifizieren. Dies ermöglicht es dir, es pro Benutzer (oder Pseudobenutzer, wenn du eine IP-Adresse verwendest) nachzuschlagen.

Zum Beispiel (mit einer Datei):

$uploads = unserialize(file_get_contents('uploads.txt');
if(!$uploads) $uploads = array();

// Um den Benutzer zu aktualisieren (unter Verwendung von Variablen aus dem obigen Beispiel)
$uploads[$_SERVER['REMOTE_ADDR']] = array('total_uploads' => $uploaded_images + $total_uploads_so_far, 'last_upload' => time());

file_put_contents('uploads.txt', serialize($uploads));

0voto

Andrew Willis Punkte 2249

Der beste Weg, damit umzugehen, wäre die Uploads über die IP-Adresse zu verfolgen, was jedoch nicht zu 100% genau ist.

Erstellen Sie eine Datenbanktabelle uploads wie folgt:

--------------------------------------------------------------------------------------
|  id (unsigned int, auto increment) |  ip (varchar) |  timestamp (aktueller Zeitstempel)|
--------------------------------------------------------------------------------------

Führen Sie dann die folgende Abfrage aus, um herauszufinden, wie viele der Benutzer in der letzten halben Stunde hochgeladen hat

SELECT * FROM `uploads` WHERE `ip` = '{$userIP}' AND `timestamp` > DATE_SUB(NOW(), INTERVAL 30 MINUTE)

Zählen Sie die Zeilen mithilfe Ihrer gewählten PHP-Datenbank-Wrapper-Zählmethode und wenn die Anzahl kleiner als 10 ist, erlauben Sie das Speichern des Bildes.

Wenn das Bild hochgeladen wird, führen Sie aus:

INSERT INTO `uploads` (`ip`) VALUES ('{$userIP}')

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