Wie wird die Eingabe- und Parameterüberprüfung zwischen Layern durchgeführt?

8

Wenn ich über eine Webformularanwendung mit drei Ebenen verfüge, die Benutzereingaben akzeptiert, weiß ich, dass ich diese Eingabe mithilfe von Validierungssteuerelementen in der Präsentationsebene überprüfen kann. Sollte ich auch in den Geschäfts- und Datenschichten validieren, um vor SQL-Injection und auch Problemen zu schützen? Welche Validierungen sollten in jeder Schicht gehen?

Ein anderes Beispiel wäre die Übergabe einer ID, um einen Datensatz zurückzugeben. Sollte die Datenschicht sicherstellen, dass die ID gültig ist oder sollte dies in BLL / UI passieren?

    
jpshook 05.03.2010, 15:22
quelle

6 Antworten

7

Sie sollten in allen Layern Ihrer Anwendung validieren .

Welche Validierung für jede Ebene durchgeführt wird, ist spezifisch für die Ebene selbst. Jede Schicht sollte sicher sein, "schlechte" Anforderungen zu senden und eine sinnvolle Antwort zu erhalten, aber welche Prüfungen für jede Schicht durchgeführt werden, hängt von Ihren spezifischen Anforderungen ab.

Allgemein:

  • Benutzeroberfläche - Sollte Benutzereingaben validieren, hilfreiche Fehlermeldungen und visuelle Hinweise zu ihrer Behebung geben; Es sollte Ihre unteren Schichten gegen ungültige Benutzereingaben schützen.
  • Business / Domain Layer - Sollte prüfen, ob Argumente für Methoden gültig sind ( ArgumentException und ähnliche wenn nicht) und überprüfen, ob Operationen innerhalb der Beschränkungen Ihrer Geschäftsregeln möglich sind; Es sollte Ihre Domain vor Programmierfehlern schützen.
  • Datenschicht - Sollte überprüfen, dass die Daten, die Sie einfügen oder aktualisieren möchten, im Kontext Ihrer Datenbank gültig sind, dass sie alle relationalen Einschränkungen und Prüfbedingungen erfüllen; Es sollte Ihre Datenbank vor Fehlern beim Datenzugriff schützen.

Die Validierung auf jeder Ebene stellt sicher, dass nur Daten und Vorgänge, die die Ebene für richtig hält, betreten werden dürfen. Dies gibt Ihnen ein hohes Maß an Vorhersagbarkeit, weil Sie wissen mussten, dass Informationen bestimmte Kriterien erfüllen mussten, um in Ihrer Datenbank durchzukommen, dass Operationen logisch sein mussten, um Ihre Domänenebene zu erreichen, und dass Benutzereingaben bereinigt und einfacher zu handhaben waren mit.

Es gibt Ihnen auch die Sicherheit, dass wenn eine Ihrer Ebenen unterlaufen ist, eine andere Ebene dahinter Prüfungen durchführt, die verhindern sollen, dass etwas eintritt, was Sie nicht wollen.

    
Paul Turner 05.03.2010, 15:59
quelle
5

Should I also validate in the business and data layers as well to protect against SQL injection and also issues?

Ja und ja.

In Ihrem Business-Layer-Code müssen Sie die Eingabe erneut validieren (da die Client-Seite gefälscht werden kann) und auch für Ihre Geschäftslogik, und sicherstellen, dass die Einträge für Ihre Anwendung sinnvoll sind.

Wie bei der Datenschicht müssen Sie erneut sicherstellen, dass die Daten für die Datenbank gültig sind. Verwenden Sie parametrisierte Abfragen, da dies ziemlich sicherstellt, dass keine SQL-Injektion stattfindet.

Was Ihre spezifische Frage bezüglich der ID betrifft - die DB wird wissen, ob eine ID existiert oder nicht. Ob dies zutrifft oder nicht, hängt davon ab, ob es für Ihre Business-Schicht eine Bedeutung hat oder nicht. Wenn es sich nur um ein DB-Artefakt handelt (nicht Teil Ihres Objektmodells), muss die DB als Teil des Objektmodells behandelt werden, wenn es ist und eine Bedeutung für das Objektmodell hat es.

    
Oded 05.03.2010 15:29
quelle
1

Sie müssen unbedingt in Ihren Geschäfts- und Datenschichten validieren. Die Benutzeroberfläche ist eine nicht vertrauenswürdige -Schicht. Es ist immer möglich, dass jemand Ihre clientseitige Validierung und in einigen Fällen Ihre serverseitige UI-Validierung umgehen kann.

Um die SQL-Injektion zu verhindern, müssen Sie lediglich Ihre Abfragen parametrisieren. Der Ausdruck "SQL Injection" sollte nicht mehr existieren, es ist seit Jahren ein gelöstes Problem, und trotzdem sehe ich jeden Tag Leute, die Abfragen mit String-Verkettungen schreiben. Tu das nicht. Parametriere die Befehle und alles wird gut.

Einer der Hauptgründe, warum Sie Ihre App in mehrere Ebenen aufteilen, ist, dass jede Ebene wiederverwendbar ist. Wenn einzelne Ebenen ihre eigene Validierung nicht durchführen, sind sie nicht autonom und Sie haben keine ordnungsgemäße Trennung von Bedenken. Sie können auch keine eingehenden Tests durchführen, ohne dass einzelne Komponenten eine integrierte Validierung durchführen.

Ich lockere diese Einschränkungen für Klassen oder Methoden, die internal oder private sind, weil sie nicht direkt getestet oder verwendet werden. Solange die öffentliche API vollständig validiert ist, können private APIs im Allgemeinen davon ausgehen, dass sich die Klasse in einem gültigen Status befindet.

Also, im Grunde, ja, jeder Layer, in der Tat jede öffentliche Klasse und Methode muss seine eigenen Daten / Argumente validieren.

Die semantische Validierung, wie die Überprüfung, ob eine bestimmte Kunden-ID gültig ist oder nicht, hängt von Ihren Design-Anforderungen ab. Offensichtlich hat die Business-Schicht keine Möglichkeit zu wissen, ob eine ID existiert oder nicht, bis diese ID tatsächlich auf die Datenschicht trifft, so dass sie diese Überprüfung nicht im Voraus durchführen kann. Ob es eine Ausnahme für eine fehlende ID auslöst oder einfach null zurückgibt / den Fehler ignoriert, hängt davon ab, wofür die Klasse / Methode vorgesehen ist.

Wenn diese ID jedoch in einem speziellen Format vorliegen muss - zum Beispiel verwenden Sie möglicherweise speziell codierte Kontonummern ("R-12345-A-678") -, liegt dies in der Verantwortung der Domain / Business-Schicht, um die Eingabe zu überprüfen und sicherzustellen, dass sie dem korrekten Format entspricht, insbesondere wenn der Consumer Ihrer Business-Klasse versucht, ein neues Konto zu erstellen.

    
Aaronaught 05.03.2010 15:30
quelle
1

Keine Ebene sollte Daten vertrauen, die von einer anderen Ebene kommen. Die Analogie, die ich dafür verwende, ist eine der Lehen. Sagen Sie, Sie möchten eine Nachricht an den König senden. Wenn die Nachricht nicht im richtigen Format ist, wird sie abgelehnt, bevor sie in die Ohren kommt. Sie könnten weiterhin Nachrichten senden, bis Sie schließlich das Format erhalten oder Sie könnten einen Emissär verwenden. Die Aufgabe des Emissärs besteht darin, Ihnen zu helfen, zu überprüfen, ob Ihre Nachricht im akzeptablen Format ist, damit der König sie hören kann.

Jede Schicht in einem System ist ein Lehen. Jede Schicht fungiert als Emissär für die Schicht, an die sie Daten sendet, indem sie überprüft, ob sie akzeptiert wird. Keine Ebene vertraut Daten, die von außerhalb dieser Ebene kommen (niemand vertraut Nachrichten von außerhalb des Lehens). Die Datenbank vertraut der mittleren Ebene nicht. Die mittlere Schicht vertraut der Datenbank oder der Präsentationsebene nicht. Die Präsentation vertraut dem Benutzer oder der mittleren Ebene nicht.

Die Antwort lautet also, dass Sie die Daten in jeder Schicht unbedingt überprüfen und erneut überprüfen sollten.

    
Thomas 05.03.2010 16:01
quelle
0

Kurze Antwort: ja.

Überprüfe, wie Eingaben in jeder neuen Ebene empfangen werden und bevor sie umgesetzt werden. Im Allgemeinen validiere ich diese Eingabe, bevor sie verwendet oder an die nächste Ebene weitergegeben wird (JavaScript prüft, ob es eine gültige E-Mail ist und keine schädlichen Eingaben enthält.) Ähnlich verhält es sich mit der Business-Schicht, bevor eine Abfrage erstellt wird.)

Zu Ihrer letzten Frage: Wenn die ID einen Datensatz zurückgibt, dann ist sie gültig und Sie müssen die ID des Datensatzes finden, um zu bestätigen, ob sie gültig ist oder nicht, so dass Sie viele unnötige Suchvorgänge durchführen würden wenn du das versuchen würdest.

Ich hoffe, das hilft.

    
cazlab 05.03.2010 15:27
quelle
-1

Ich mache meine gesamte Validierung auf der Presenter-Ebene im Model-View-Presenter. Die Validierung ist etwas schwierig, weil es so oft ein übergreifendes Problem ist.

Ich bevorzuge es, dies auf der Presenter-Ebene zu tun, weil ich dann den Aufruf an das Modell kurzschließen kann.

Der andere Ansatz besteht darin, die Validierung in der Modellschicht durchzuführen, aber dann das Problem der Fehlerübertragung, da Sie abgesehen von Ausnahmen nicht einfach andere Fehlerschichten angeben können. Sie können Ausnahmen immer mit Daten packen oder eine eigene benutzerdefinierte Ausnahme erstellen, an die Sie eine Liste von Fehlermeldungen oder ähnlichen Konstrukten anhängen können, die mir aber immer schmutzig erscheinen.

Später, wenn ich mein Modell über einen Web-Service verfügbar mache, werde ich die doppelte Validierung sowohl im Presenter als auch im Model implementieren, da es möglich ist, die Presenter-Ebene zu überspringen, wenn Sie den Web-Service aufrufen. Der andere große Vorteil besteht darin, dass es meine Validierungen für den Presenter-Layer vom Modell entkoppelt, da das Modell möglicherweise nur eine rohe Validierung von Typen erfordert, um mit der Datenbank übereinzustimmen, während Benutzer meiner UI detailliertere Regeln für ihre Eingabe wünschen sie können physisch.

Andere Fragen: Der SQL-Injection-Bereich, der ein Modellproblem darstellt und sich nicht in einer der mittleren Schichten befinden sollte. Die meisten SQL-Injection-Angriffe werden jedoch vollständig aufgehoben, wenn Textfelder keine Sonderzeichen zulassen. Der andere Teil davon ist, dass Sie fast immer parametrisierte SQL verwenden sollten, was die SQL-Injektion nicht nutzbar macht.

Die Frage zu der ID, die ein Modell betrifft, kann entweder einen Datensatz mit dieser ID erhalten oder null zurückgeben oder eine Ausnahme für einen nicht gefundenen Datensatz auslösen, je nachdem, welche Konvention Sie festlegen möchten.

    
Chris Marisic 05.03.2010 15:28
quelle

Tags und Links