/ / Wie man JSON auf der Serverseite am besten validiert - json, web-services, validation, api, security

Wie man JSON am besten serverseitig validiert - json, web-services, validation, api, security

Bei der Verarbeitung von POST-, PUT- und PATCH-Anfragen auf der Serverseite müssen wir oft JSON verarbeiten, um die Anfragen auszuführen.

Es ist offensichtlich, dass wir diese JSONs (z. B. Struktur, erlaubte / erwartete Schlüssel und Werttypen) auf irgendeine Weise validieren müssen, und ich kann mindestens zwei Möglichkeiten sehen:

  1. Nach Erhalt des JSON validiere das JSON im Voraus wie es ist, Vor alles damit machen, um die Anfrage zu vervollständigen.

  2. Nimm das JSON so wie es ist, fange an, es zu verarbeiten (z. B. auf seine verschiedenen Schlüsselwerte zuzugreifen) und versuchen Sie es während der Geschäftslogik unterwegs zu validierenund möglicherweise eine Ausnahmebehandlung verwenden, um Modedaten zu verarbeiten.

Der erste Ansatz scheint im Vergleich zuDie zweite, aber wahrscheinlich teurere (in Zeitaufwand), weil jede Anfrage validiert wird (und hoffentlich die meisten von ihnen sind gültig, so dass die Validierung eine Art überflüssig ist).

Der zweite Ansatz kann die obligatorische Validierung gültiger Anforderungen ersparen, aber das Mischen der Überprüfungen innerhalb der Geschäftslogik kann fehlerhaft oder sogar riskant sein.

Welches der beiden oben genannten ist besser? Oder gibt es noch einen besseren Weg?

Antworten:

10 für die Antwort № 1

Was du mit POST, PUT und PATCH beschreibstklingt wie Sie eine REST-API implementieren. Abhängig von Ihrer Backend-Plattform können Sie Bibliotheken verwenden, die JSON Objekten zuordnen, die sehr leistungsfähig sind und diese Validierung für Sie durchführen. In JAVA können Sie verwenden Jersey, Frühling, oder Jackson. Wenn Sie .NET verwenden, können Sie verwenden Json.NET.

Wenn Effizienz Ihr Ziel ist und Sie jede einzelne Anfrage validieren möchten, wäre es ideal, wenn Sie am Frontend testen könnten, ob Sie JavaScript verwenden, das Sie verwenden können json2.js.

In Bezug auf den Vergleich Ihrer Methoden finden Sie hier eine Pro / Cons-Liste.

Methode # 1: Auf Anfrage

Pros

  1. Die Integrität der Geschäftslogik wird beibehalten. Wie Sie bereits erwähnt haben, könnte der Versuch, eine Validierung durchzuführen, während die Verarbeitung der Geschäftslogik zu ungültigen Tests führen könnte, die tatsächlich gültig sein können, und umgekehrt oder auch die Validierung könnte sich unbeabsichtigt negativ auf die Geschäftslogik auswirken.
  2. Wie Norbert bereits erwähnt hat, wird die Effizienz verbessert, wenn man die Fehler vorwegnimmt. Die logische Frage, die sich daraus ergibt, ist, warum sollte die Zeit verarbeitet werden, wenn es Fehler gibt?
  3. Der Code wird sauberer und einfacher zu lesen sein. Wenn die Validierung und die Geschäftslogik getrennt sind, wird der Code sauberer und leichter zu lesen und zu pflegen sein.

Nachteile

  1. Dies könnte zu einer redundanten Verarbeitung führen, was eine längere Rechenzeit bedeutet.

Methode 2: Validierung unterwegs

Pros

  1. Es ist theoretisch effizient, indem es Prozess spart und gleichzeitig Rechenzeit verbraucht.

Nachteile

  1. In Wirklichkeit ist die Prozesszeit, die gespeichert wirdwahrscheinlich vernachlässigbar (wie von Norbert erwähnt). Sie machen noch immer die Validierungsprüfung. Außerdem wird Verarbeitungszeit verschwendet, wenn ein Fehler gefunden wurde.
  2. Die Datenintegrität kann umfasst sein. Es könnte möglich sein, dass der JSON bei der Verarbeitung auf diese Weise beschädigt wird.
  3. Der Code ist nicht so klar. Beim Lesen der Geschäftslogik ist es möglicherweise nicht so offensichtlich, was passiert, weil die Validierungslogik eingemischt ist.

Worauf es wirklich ankommt ist Richtigkeit vs Geschwindigkeit. Sie haben im Allgemeinen eine inverse Beziehung. Wenn Sie genauer werden und Ihren JSON validieren, müssen Sie möglicherweise Kompromisse bei der Geschwindigkeit eingehen. Dies macht sich nur in großen Datensätzen bemerkbar, da Computer heutzutage sehr schnell sind. Es liegt an Ihnen, zu entscheiden, was wichtiger ist, wenn Sie angeben, wie genau Sie Ihre Daten beim Empfang verstehen, oder ob diese zusätzliche Sekunde entscheidend ist. In einigen Fällen spielt es eine Rolle (d. H. Bei den Börsen- und Gesundheitsanwendungen sind Millisekunden wichtig) und beide sind sehr wichtig. In diesen Fällen müssen Sie, wenn Sie beispielsweise die Genauigkeit erhöhen, die Geschwindigkeit erhöhen, indem Sie eine leistungsfähigere Maschine erhalten.

Hoffe das hilft.


6 für die Antwort № 2

Der erste Ansatz ist robuster, tut dies aber nichtmuss deutlich teurer sein. Selbst wenn Sie den Parsing-Prozess aufgrund von Fehlern abbrechen können, wird es wesentlich kostengünstiger: Ihre Geschäftslogik benötigt normalerweise> 90% der Ressourcen in einem Prozess. Wenn Sie also einen Fehler% von 10% haben, sind Sie bereits ressourcenneutral . Wenn Sie den Validierungsprozess so optimieren, dass die Validierungen aus dem Geschäftsprozess im Voraus durchgeführt werden, ist Ihre Fehlerrate möglicherweise viel niedriger (wie 1 zu 20 bis 1 zu 100), um ressourcenneutral zu bleiben.

Ein Beispiel für eine Implementierung, die eine Datenvalidierung voraussetzt, finden Sie unter GSON (https://code.google.com/p/google-gson/):

GSON funktioniert folgendermaßen: Jeder Teil des JSON kann in ein Objekt umgewandelt werden. Dieses Objekt ist getippt oder enthält typisierte Daten: Beispielobjekt (JAVA als Beispielsprache):

public class someInnerDataFromJSON {
String name;
String address;
int housenumber;
String buildingType;
// Getters and setters
public String getName() { return name; }
public void setName(String name) { this.name=name; }
//etc.
}

Die von GSON analysierten Daten verwenden das bereitgestellte Modell, das bereits typisiert ist. Dies ist der erste Punkt, an dem Ihr Code abbrechen kann.

Nachdem dieser Ausgangspunkt die dem Modell bestätigten Daten angenommen hat, können Sie überprüfen, ob die Daten innerhalb bestimmter Grenzen liegen. Sie können das auch in das Modell schreiben.

Angenommen, für diesen buildingType gibt es eine Liste:

  • Einfamilienhaus
  • Mehrfamilienhaus
  • Wohnung

Sie können Daten während des Parsens überprüfen, indem Sie ein erstellenSetter, der die Daten prüft, oder Sie können es nach dem Parsen in einem ersten Satz Ihrer Geschäftsregelanwendung überprüfen. Der Vorteil der ersten Überprüfung der Daten besteht darin, dass Ihr späterer Code weniger Ausnahmebehandlung hat, also weniger und einfacher zu verstehen ist.


1 für die Antwort № 3

Im Allgemeinen wäre die erste Option der Weg zu gehen. Der einzige Grund, warum Sie möglicherweise an die zweite Option denken müssen, ist, wenn Sie mit JSON-Daten arbeiten, die mehrere Dutzend MB groß oder größer sind.

Mit anderen Worten, nur wenn Sie versuchen, JSON zu streamen und es im laufenden Betrieb zu verarbeiten, müssen Sie über die zweite Option nachdenken.

Unter der Annahme, dass Sie pro JSON höchstens einige hundert KB groß sind, können Sie einfach die erste Option wählen.

Hier sind einige Schritte, die Sie verfolgen könnten:

  1. Gehen Sie für einen JSON-Parser wie GSON, der nur würdeKonvertiere dein gesamtes JSON-Eingabe in das entsprechende Java-Domänenmodellobjekt. (Wenn GSON Keine Ausnahme, Sie können sicher sein, dass der JSON ist absolut gültig.)
  2. Natürlich, die Objekte, die gebaut wurdenVerwenden von GSON in Schritt 1 möglicherweise nicht in einem funktional gültigen Zustand. Zum Beispiel, funktional Checks wie Pflichtfelder und Limit-Checks müssten gemacht werden.
  3. Dazu könnten Sie eine validateState-Methode definieren, die wiederholt überprüft die Zustände des Objekts selbst und seiner untergeordneten Objekte.

Hier ist ein Beispiel für eine validateState Methode:

public void validateState(){
//Assume this validateState is part of Customer class.

if(age<12 || age>150)
throw new IllegalArgumentException("Age should be in the range 12 to 120");
if(age<18 && (guardianId==null || guardianId.trim().equals(""))
throw new IllegalArgumentException("Guardian id is mandatory for minors");

for(Account a:customer.getAccounts()){
a.validateState(); //Throws appropriate exceptions if any inconsistency in state
}
}

1 für die Antwort № 4

Ich würde definitiv für die Validierung vor der Verarbeitung gehen.

Sagen wir, Sie erhalten etwas json Daten mit 10 Variablen, von denen Sie erwarten:

  • die ersten 5 Variablen sind vom Typ Zeichenfolge
  • 6 und 7 sollen sein ganze Zahlen
  • 8, 9 und 10 sollen sein Arrays

Sie können eine schnelle Validierung des Variablentyps durchführen, bevor Sie mit der Verarbeitung dieser Daten beginnen und eine Validierungsfehlerantwort zurückgeben, wenn einer der zehn Fehler auftritt.

foreach($data as $varName => $varValue){
$varType = gettype($varValue);
if(!$this->isTypeValid($varName, $varType)){
// return validation error
}
}

// continue processing

Denken Sie an das Szenario, in dem Sie direkt sindVerarbeitung der Daten und dann der 10. Wert erweist sich als ungültiger Typ. Die Verarbeitung der vorherigen 9 Variablen war eine Verschwendung von Ressourcen, da Sie auf jeden Fall irgendeine Validierungsfehlerantwort zurückgeben. Darüber hinaus müssen Sie alle Änderungen, die bereits in Ihrem Speicher vorhanden sind, zurücksetzen.

Ich verwende in meinem Beispiel nur den Variablentyp, aber ich würde eine vollständige Validierung (Länge, Max / Min-Werte usw.) aller Variablen vor der Verarbeitung von ihnen vorschlagen.


1 für die Antwort № 5

Die Antwort hängt vollständig von Ihrem Anwendungsfall ab.

Wenn Sie erwarten, dass alle Aufrufe von vertrauenswürdigen Clients stammen, sollte die Upfront-Schemaüberprüfung implementiert werden, sodass sie nur aktiviert wird, wenn Sie ein Debug-Flag setzen.

Wenn Ihr Server jedoch öffentliche API bereitstelltDienste, dann sollten Sie die Anrufe im Voraus validieren. Dies ist nicht nur ein Leistungsproblem - Ihr Server wird wahrscheinlich von Ihren Kunden, Hackern, Rivalen usw. auf Sicherheitslücken untersucht.

Wenn Ihr Server private API-Dienste bereitstelltnicht vertrauenswürdige Clients (z. B. in einem geschlossenen Netzwerk-Setup, wo es mit Systemen von Drittanbieter-Entwicklern zu integrieren ist), dann sollten Sie zumindest diese Schecks im Voraus ausführen, die Sie davor bewahren, für die Dummheiten anderer verantwortlich gemacht zu werden.


1 für die Antwort № 6

Es hängt wirklich von Ihren Anforderungen ab. Aber im Allgemeinen würde ich immer gehen # 1.

Wenige Überlegungen:

Aus Konsistenz würde ich Methode verwenden # 1, für die Leistung # 2. Allerdings bei der Verwendung # 2 Sie müssen berücksichtigen, dass das Zurückrollen im Falle einer ungültigen Eingabe in der Zukunft kompliziert werden kann, wenn sich die Logik ändert.

Die JSon-Validierung sollte nicht so lange dauern. In Python können Sie verwenden Ujson zum Parsen von JSON-Strings, das ist a ultraschnelle C-Implementierung des Json Python-Modul.

Zur Validierung verwende ich die jsonschema Python-Modul, das JSON-Validierung einfach macht.

Ein anderer Ansatz:

wenn du benutzt jsonschema, können Sie die JSON-Anfrage in Schritten validieren. Ich würde eine erste Validierung der häufigsten / wichtigsten Teile der JSON-Struktur durchführen und die verbleibenden Teile entlang des Geschäftslogikpfads validieren. Dies würde es ermöglichen, einfachere JSON-Schemata zu schreiben und daher leichter zu sein.

Die endgültige Entscheidung:

Wenn (und nur wenn) diese Entscheidung kritisch ist, würde ich beide Lösungen implementieren, sie in richtigen und falschen Eingabebedingungen zeitlich abbilden und die Ergebnisse abhängig von der falschen Eingabefrequenz gewichten.

  • 1c = durchschnittliche Zeit, die mit Methode 1 verbracht wurde correct Eingabe
  • 1w = durchschnittliche Zeit, die mit Methode 1 verbracht wurde wrong Eingabe
  • 2c = durchschnittliche Zeit, die mit Methode 2 verbracht wurde correct Eingabe
  • 2W = durchschnittliche Zeit, die mit Methode 2 verbracht wurde wrong Eingabe
  • CR = correct Eingabe rgegessen (oder Häufigkeit)
  • WR = wrong Eingabe rgegessen (oder Häufigkeit)

    if ( 1c * CR ) + ( 1w * WR) <= ( 2c * CR ) + ( 2w * WR):
    chose method 1
    else:
    chose method 2