Sollten Sicherheitsbeschränkungen dazu führen, dass ein Dienst null zurückgibt oder eine Ausnahme auslöst? [geschlossen]

11

Ich bin mit einem erfahreneren Entwickler in dieser Frage nicht einverstanden und frage mich, was andere darüber denken. Unsere Umgebung ist Java, EJB 3, Services usw.

Der Code, den ich geschrieben habe, ruft einen Dienst auf, um Dinge zu bekommen und Dinge zu erstellen. Das Problem, auf das ich stieß, war, dass ich Nullzeigerausnahmen bekam, die keinen Sinn machten. Wenn ich beispielsweise den Dienst auffordere, ein Objekt zu erstellen, erhalte ich null zurück. Wenn ich versuche, ein Objekt mit einer bekannten gültigen ID nachzuschlagen, erhalte ich null zurück. Ich habe einige Zeit damit verbracht herauszufinden, was in meinem Code falsch war. Da ich weniger erfahren bin, gehe ich normalerweise davon aus, dass ich etwas falsch gemacht habe, aber es stellt sich heraus, dass der Grund für die Null-Rückgabe die Sicherheit war. Wenn der Benutzerprinzipal, der meinen Dienst verwendet, nicht über die richtigen Berechtigungen für den Zieldienst verfügt, wird einfach null zurückgegeben. Die meisten anderen Dienste hier sind ebenfalls nicht sehr gut dokumentiert, daher ist dies anscheinend nur etwas, was Sie wissen müssen.

Dies ist ziemlich verwirrend, da Entwickler Code schreiben, der mit dem Dienst interagiert. Es wäre für mich viel sinnvoller, wenn der Dienst eine Ausnahme wäre, die mir sagt, dass der Benutzer nicht über die richtigen Berechtigungen zum Laden oder Erstellen dieses Dings verfügt. Ich würde dann sofort wissen, warum mein Service nicht wie erwartet funktioniert.

Der erfahrenere Entwickler, der den Service geschrieben hat, argumentierte, dass das Anfordern der Daten keine Fehlerbedingung ist und dass Ausnahmen nur in einer Fehlerbedingung ausgelöst werden sollten, nicht wenn der Benutzer keinen Zugriff auf die Daten hat. Diese Daten werden häufig in einer GUI nachgeschlagen, und für Benutzer ohne die richtigen Berechtigungen sind diese Dinge einfach "nicht vorhanden". Kurz gesagt: Fragen ist nicht falsch, daher keine Ausnahme. Get-Methoden geben null zurück, da diese Dinge für diese Benutzer "nicht vorhanden" sind. Erstellungsmethoden geben null zurück, wenn der Benutzer das Ding nicht erstellen durfte.

Ist das normal und / oder eine gute Praxis? Ich bevorzuge Ausnahmen, weil ich es viel einfacher finde zu wissen, was los ist. So würde ich zum Beispiel auch lieber eine NotFoundException auslösen, wenn Sie nach einem Objekt mit einer ungültigen ID gefragt haben, anstatt null zurückzugeben.

Svish
quelle
@ChrisF: 1) handelt von Leuten, die Nullreferenzen meiden, was ich nicht tue. In vielen Fällen sind sie angemessen, ich glaube einfach nicht, dass sie in diesem Fall sind. 2) geht es darum, Parameter zu überprüfen, und würde eine Behauptung nicht gleichbedeutend mit dem Auslösen einer Ausnahme sein? 3) Ausnahmen gegen Fehlercodes sind ebenfalls ein anderes Problem, da beide Möglichkeiten sind, um zu "zeigen", was schief gelaufen ist. Fehlercodes sind geeignet, wenn Sie beispielsweise ein System benachrichtigen müssen, das keine Ausnahmen unterstützt, oder wenn der Endbenutzer nur einen Code sehen soll.
Svish
Das Problem, nach dem ich hier frage, ist "vorgeben, dass etwas nicht existiert oder nicht passiert ist" oder "warum etwas nicht existiert oder nicht passiert ist".
Svish
3
Ich habe nicht vorgeschlagen, dass es sich um Duplikate handelt - nur damit sie nützliche Informationen für Sie haben.
ChrisF
Stimmt, tut mir leid! Ich habe es aus irgendeinem Grund als "mögliche Duplikate" -Kommentar verstanden ... wahrscheinlich wegen Schlafmangels, hehe.
Svish

Antworten:

20

Ausnahmen sollten nur ausgelöst werden, wenn ein Fehler vorliegt und das Bitten um etwas kein Fehler ist.

Nach etwas zu fragen ist vielleicht kein Fehler, aber keine Berechtigung für etwas zu haben, nach dem Sie gefragt haben, ist sicherlich eine Art Fehler. Ausnahmen sind eine alternative Möglichkeit, außergewöhnliche Bedingungen zu melden, die anstelle spezieller Rückgabewerte verwendet werden sollen (z. B. nullwas, wie Sie geschrieben haben, absolut keine Hilfe ist, wenn es> 1 mögliche Gründe gibt, warum Dinge schief gehen könnten (selbst wenn dies der Fall ist) Genau 1 möglicher Grund jetzt, es könnte 2 mögliche Gründe in der nächsten Version geben, also würde die Verwendung nullals Rückgabewert, der einen Fehler anzeigt, bedeuten, dass Sie sich selbst in die Ecke malen)). Wenn der Service in keiner Weise meldet, warum er nicht das tut, wonach Sie gefragt haben, ist das Design definitiv schlecht.

Ob ein spezieller Rückgabewert verwendet werden soll (z. B. negative Ganzzahlen sind nützlich für Funktionen, die normalerweise eine nichtnegative Ganzzahl zurückgeben), eine Ausnahme, ein globaler Fehlerbehandler oder Logger usw., ist am Ende ein Implementierungsdetail. Die Wahl hängt von der Sprache, der Situation, den Konventionen ab und ist auch eine Frage des Geschmacks. Der Hauptpunkt ist, dass es einen direkten Weg geben sollte, um herauszufinden, warum etwas nicht funktioniert. Andernfalls besteht Ihre einzige Möglichkeit darin, mit verschiedenen Optionen und was auch immer herumzusuchen, um herauszufinden, was mit dem Verhalten der Black Box korreliert, und es ist Zeitverschwendung.

String.substring()wirft ein, IndexOutOfBoundsExceptionwenn der Index außerhalb der Grenzen liegt. Ich kann mir keine Vorteile für die Rückkehr nullvorstellen, obwohl man - philosophisch gesehen - argumentieren könnte, dass a Stringnichts außerhalb seiner Grenzen enthält, also nullwäre dies ein logischer Rückgabewert. Logisch-philosophisch und praktisch zu sein, sind offensichtlich zwei verschiedene Tiere.

Joonas Pulakka
quelle
Wenn substring () einen Wert für Indizes außerhalb der Grenzen zurückgeben soll, sollte der Teil der Zeichenfolge zwischen den Indizes zurückgegeben werden, möglicherweise leer. Das könnte einen Test in einem aufrufenden Code speichern.
Kevin Cline
2
Ja, es gibt diesen nie endenden "leeren Wert" im Vergleich zur Null-Diskussion: Sollte der Teilstring für nicht gebundene Indizes null oder eine leere Zeichenfolge sein? Ich weiß nicht, beide sind effektiv "nichts" (naja, vielleicht ist null "mehr nichts" als eine leere Zeichenfolge?), Aber keiner gibt die Menge an Informationen an, die eine Ausnahme liefert.
Joonas Pulakka
@kevincline: Wenn man kein Framework verwendet, in dem eine Nullreferenz ein idiomatisches Mittel zur Angabe einer leeren Zeichenfolge ist, sehe ich keine Grundlage für substringdie Rückgabe einer Nullreferenz. IMHO sollte es zwei separate Funktionen geben - eine verspricht, entweder die angeforderte Anzahl von Zeichen zurückzugeben oder eine Ausnahme auszulösen, und eine gibt so viel wie möglich zurück. Jede Methode wäre in einigen Zusammenhängen der anderen wesentlich überlegen.
Supercat
@supercat: Ich habe nichts über die Rückgabe von null gesagt. Ich sagte 'Rückkehr ... das Teil ... möglicherweise leer'. Eine leere Zeichenfolge ist außer für Oracle nicht null.
Kevin Cline
@JoonasPulakka: Ich hätte dich zu meinem vorherigen Kommentar pingen sollen.
Supercat
5

Es kommt darauf an, was der Vertrag ist. Wenn Ihr Vertrag besagt, dass Sie etwas anfordern können, das nicht existiert, sollte er angeben, was passiert (null oder null Objekt).

Wenn Ihr Vertrag jedoch besagt, dass Sie zuerst eine andere Methode aufrufen sollten ( DoesSomethingExist()) und dann die GetMethode aufrufen sollen , könnte Ihr Vertrag möglicherweise besagen, dass Sie nur vorhandene Elemente abrufen und eine Ausnahme auslösen können, wenn dies nicht der Fall ist. Die Ausnahmemeldung könnte etwa " DoesSomethingExist()Zuerst anrufen" lauten, was eine nützliche Fehlermeldung ist.

Scott Whitlock
quelle
In diesem Fall würde ich sagen, dass es nicht normal ist, nach etwas zu fragen, das nicht existiert, da Sie wahrscheinlich nicht nach einer ID fragen würden, die nicht existiert. Normalerweise hätten Sie zuerst eine Liste der Dinge erhalten und dann eine bestimmte nachgeschlagen, um weitere Einzelheiten zu erfahren. Wenn es also eine findAllThingsMethode gäbe, würde ich sagen, dass es angemessen ist, eine leere Liste oder eine Teilmenge zurückzugeben, wenn es einige oder alle Dinge gibt, die Sie nicht sehen dürfen. Auf die gleiche Weise könnte ich in einem Blog nur Beiträge zum Bearbeiten auflisten, die dem aktuellen Benutzer gehören. Aber wenn dieser Benutzer dann versucht hat, die URL zu optimieren und einen anderen Beitrag zu bearbeiten ...
Svish
4

Es gibt keine einheitliche Antwort auf die Frage. Ob Ausnahmen verwendet werden oder null zurückgegeben wird, hängt von der jeweiligen Situation ab.

Anstatt dies nur aus dogmatischer Sicht zu betrachten, betrachten Sie die Benutzeroberfläche als Benutzeroberfläche . Benutzeroberflächen sollten verwendbar sein . Wählen Sie also unabhängig von Ihrer eigenen Meinung zur "richtigen" Vorgehensweise die Methode aus, die aus der Sicht einer Person, die Ihre Benutzeroberfläche verwendet, am besten geeignet ist.

Wenn der Aufrufer wissen muss, warum ein Objekt nicht zurückgegeben wird, ist eine Ausnahme angebracht. Wenn das allgemeine Konzept jedoch lautet: "Wenn Sie keine Berechtigung haben, existiert sie nicht", ist die Null akzeptabel.

Insbesondere in Ihrem Fall würde ich sagen, dass Nullen für die Suche nach einem Element durchaus akzeptabel sind, wenn der Anrufer sich zuerst anmelden oder eine Verbindung zum Server herstellen muss. Dann wird Ihnen gesagt, dass Sie die Erlaubnis haben oder nicht. Sobald Sie das Tor passiert haben, ist es vernünftig, dass Sie bei der Suche nach etwas, das Sie nicht sehen dürfen (oder gar wissen, dass es existiert), eine Null erhalten sollten.

Wenn Sie andererseits keine anfängliche Verbindung oder keinen Anmeldeschritt haben, ist eine Ausnahme sinnvoll. Wenn der Anrufer weiß, dass ein Element vorhanden ist und es nicht zurückerhält, ist die API nicht hilfreich, um nur eine Null zurückzugeben.

Für das Erstellen eines Elements ist dies jedoch eine andere Geschichte. Vermutlich kann es viele Gründe dafür geben, dass dies fehlschlägt - keine Berechtigungen, fehlerhafte Parameter, nicht genügend Arbeitsspeicher usw. Wenn der Entwickler für all diese Bedingungen eine Null erhält, kann er keine geeignete Vorgehensweise festlegen .

Um die Frage zu beantworten, fragen Sie sich, welche Lösung aus der Sicht einer Person, die den Dienst nutzt, am nützlichsten ist. Es kann sein, dass die Art und Weise, wie Sie es verwenden, untypisch ist und im häufigsten Fall eine Null die richtige Antwort ist.

Also, geraten Sie nicht in einen religiösen Krieg, sondern entscheiden Sie, was für dieses spezielle Problem richtig ist.

Bryan Oakley
quelle
Ich habe nicht vor, darüber Kampfausrüstung anzulegen, hehe. War nur neugierig zu wissen, ob ich völlig falsch gedacht habe, was ich dachte oder nicht. Ich möchte lernen, aber ich mag es nicht, zu etwas zu springen, nur weil eine Person es sagt. Und vor allem nicht, wenn es meiner eigenen Erfahrung und Logik widerspricht (egal wie klein). Wie auch immer, ich stimme voll und ganz zu, dass wenn dies eine Endbenutzeroberfläche wäre, dies tatsächlich Sinn machen könnte. Da dies eine Bohne ist jedoch, die, soweit ich weiß, nur durch Code zugegriffen werden kann, würde ich sagen , dass ich als Entwickler, ist der Benutzer.
Svish
1
Und als Entwickler ist es mir wichtig, warum etwas nicht stimmt, unabhängig davon, was der Endbenutzer darüber erfahren sollte.
Svish
Stimme Bryan voll und ganz zu. Sogar Entwickler sind Benutzer, dh sie verbrauchen Code anderer Entwickler. Die Entscheidung über throw oder null ist eine Art Schnittstelle / GUI, die für die jeweilige Aufgabe hilfreich sein sollte. Nicht nur nach dem allgemeinen Begriff der Logik oder Philosophie.
Unabhängiger
3

Ich denke definitiv, dass es ein schlechtes Design ist . Der Nullzeiger ist für mich keine gültige Antwort und kann schwierig zu verwalten sein.

Wenn der Benutzer versucht, einen Dienst ohne die richtigen Anmeldeinformationen zu verbinden, sollte ich mit einer klaren und präzisen Antwort antworten. Die Antwort könnte eine Ausnahme oder ein spezielles Objekt sein, aber nicht null.

Sie sollten die Nullantwort belassen, wenn die Netzwerkverbindung unterbrochen ist oder eine andere unerwartete kritische Fehlfunktion vorliegt.

Darüber hinaus ist die Zeit, die Sie damit verbringen, zu verstehen, warum Sie eine Null erhalten haben, ein starkes Argument. Jeder Code sollte leicht zu verstehen und zu verwenden sein. Ein Nullwert ist nicht der Fall.

Amin
quelle
Meinen Sie mit Ihrem letzten Satz "Sie sollten nur dann null zurückgeben , wenn die Netzwerkverbindung unterbrochen ist usw." oder "Sie sollten aufhören, null zurückzugeben, wenn die Netzwerkverbindung unterbrochen ist usw." ?
Péter Török
@ Péter Török: Ich empfehle nicht die explizite Verwendung von "return null;". Wenn jedoch ein schwerwiegender Ausfall auftritt, ist es für einige Dienste akzeptabel, null zurückzugeben.
Amine
Wäre eine Ausnahme nicht angemessener, wenn eine unerwartete kritische Fehlfunktion auftreten würde?
Svish
2
@Amine: Ich würde sagen, dass dies der am wenigsten geeignete Fall ist, um null zurückzugeben.
Michael Borgwardt
@Svish: Wenn Sie den Hauptausfall erkennen können, ist eine Ausnahme natürlich großartig.
Amine
3

Unter Berücksichtigung eines guten Software-Designs sollten Sie über die Lebensdauer Ihres Projekts nachdenken.
Durch die Rücksendung nullgeben Sie dem Kunden, wie bereits gesagt, keine Informationen. Schauen Sie, was mit Ihnen passiert ist. Zuerst haben Sie nicht bemerkt, wo das Problem liegt. Wenn keine Dokumentation angegeben wird, ist dies ein Chaos.

Wenn Sie eine Ausnahme auslösen, können Sie feststellen, was schief gelaufen ist. Sie können den angezeigten Text sogar genauer anpassen, wenn Sie möchten.

Wenn nullSie jedoch zurückkehren, lassen Sie den Kunden untersuchen, was gerade passiert.

Außerdem haben Sie festgestellt, dass es ein Problem gibt, weil Sie woanders hingekommen sind NullPointerException. Stellen Sie sich nun vor, Sie speichern die Rückgabe dieser Funktion nicht ... Sie werden gezwungen sein, jeden Aufruf dieser Funktion mit einem if elseBlock zu umgeben ...

Aus meiner Sicht ist die Rückkehr nulleine schlechte Praxis.

Eversor
quelle
2

Der erfahrenere Entwickler, der den Service geschrieben hat, argumentierte, dass das Anfordern der Daten keine Fehlerbedingung ist und dass Ausnahmen nur in einer Fehlerbedingung ausgelöst werden sollten, nicht wenn der Benutzer keinen Zugriff auf die Daten hat.

Aus meiner Sicht macht dies keinen Sinn.

Das Abfragen von Daten ohne Berechtigung sollte zu einer Ausnahme führen, da es sich um ein unerwartetes Ergebnis handelt - um kein Ergebnis zu erhalten - ohne ordnungsgemäßen Zugriff.

Analogie : Der Antwortcode für eine GETohne Autorisierung ist nicht 200 okohne Daten, sondern tatsächlich 401 Unauthorized.

Thomas Junk
quelle
1

Null zurückzugeben ist nicht großartig. Es sagt dir nichts. Wenn eine App versucht, etwas nachzuschlagen, und die Antwort für beide Sicherheitsprobleme null ist und wenn das Element nicht vorhanden ist, wie erkennen Sie dann den Unterschied zwischen den beiden?

Eine aussagekräftige Antwort kann es der Anwendung ermöglichen, logische Entscheidungen darüber zu treffen, was als nächstes zu tun ist oder wie Probleme zu lösen sind.

Qwerky
quelle
Sie fragen, wie Sie den Unterschied zwischen einem nicht vorhandenen Objekt und der fehlenden Berechtigung zum Anzeigen erkennen können. Möglicherweise erfordert das Design des Systems, dass Sie nicht wissen. Ich denke, wir haben nicht genug Informationen, um in diesem speziellen Fall zu antworten, und es gibt keine Antwort, die in allen Fällen funktioniert. Es gibt durchaus gültige Anwendungsfälle, in denen es effektiv nicht vorhanden ist, wenn Sie es nicht sehen können. Und es gibt Anwendungsfälle, in denen Sie eine Ausnahme erhalten sollten, wenn Sie es nicht sehen können, um zu sagen, warum Sie es nicht können.
Bryan Oakley
Was meinen Sie mit "das Design des Systems erfordert, dass Sie es nicht wissen"? Was für ein Design könnte das sein?
Svish
2
Wenn die Sicherheitsrichtlinie besagt, dass Sie sie nicht sehen dürfen, sollten Sie in den meisten Fällen auch nicht wissen können, dass sie vorhanden ist. Das macht die Rückgabe "nicht gefunden" durchaus akzeptabel.
Blrfl
1

Wenn die Hauptursache ein nicht authentifizierter Benutzer ist, bevorzuge ich eine harte HTTP 401-Antwort, möglicherweise mit einer Weiterleitung zu einer hübschen Nachrichtenseite (und einer Benachrichtigung an jemanden, der sich darum kümmert). Zulassungsbedingte Ursachen treten eher von Fall zu Fall auf. Es gibt Argumente für die Rückgabe von HTTP-Fehlern (z. B. 403) und Argumente für die Rückgabe spezieller wohlgeformter Codes / Nachrichten in der Dienstantwort.

Ausnahmen sollten nur unter außergewöhnlichen Umständen verwendet werden und bedeuten, dass etwas schief gelaufen ist. Ich bin nicht der Meinung, dass sie überladen werden sollten, um "nicht erlaubt" zu bedeuten. (Gleiches gilt für den Null-Rückgabewert: Ich bin nicht der Meinung, dass er "nicht erlaubt" bedeuten sollte.)

Kennzeichen
quelle
Nun, in der GUI könnten Sie dies tun, aber für die Bean, die den Service implementiert, der die Dinge hinter den Kulissen erledigt, stehen Ihnen nur Ausnahmen und spezielle Rückgabewerte zur Verfügung. Ich meine natürlich nicht, dass der Benutzer die Ausnahme erhalten soll, aber die Ausnahme könnte zum Beispiel im Webdienst / Servlet / was auch immer abgefangen werden und dann tun, was angemessen ist. Weiterleiten an einen Ort, eine feste http 4xx-Seite oder etwas anderes.
Svish
Guter Punkt, aber Sie könnten ein Paradigma wie AOP verwenden, um diese Fälle zu erfassen. Der Aspekt könnte testen, ob er berechtigt ist, eine bestimmte Operation aufzurufen und die Verarbeitung entsprechend umzuleiten / fortzusetzen.
Mark
0

Um Devils Advocate zu spielen, werde ich versuchen, die Seite der Rückgabe von Null zu vertreten.

Meiner Meinung nach gibt es nur eine Situation, in der diese Art der Reaktion nahezu akzeptabel ist, und zwar wie in diesem Fall, wenn es um Sicherheit geht.

Es ist sehr einfach, versehentlich Details Ihres Systems preiszugeben, von denen Unbefugte nichts wissen sollten. Dies sollte vermieden werden.

Nehmen Sie zum Beispiel einen Prüfer für Benutzername und Passwort. Das Zurückgeben eines Fehlers "Benutzername nicht gefunden" und eines Fehlers "Falsches Passwort" als separate Fehlercodes würde Sie offensichtlich für schwerwiegende Sicherheitsprobleme öffnen, da jemand zuerst nach einem gültigen Benutzernamen und dann nach einem Passwort suchen könnte. Die Rückgabe eines generischen "Ungültigen Benutzernamens / Passworts" wäre eine bessere Option.

In diesem speziellen Fall würde ich sagen, dass es fast in Ordnung ist, zurückzukehren, nullaber ich stimme zu, es wäre sehr unangenehm, damit zu arbeiten.

OldCurmudgeon
quelle
Ja, ich würde nicht zustimmen. Die richtige Antwort dort wäre meiner Meinung nach eine Ausnahme, aber die gleiche für den nicht gefundenen Benutzernamen und das falsche Passwort. FailedToLogin, InvalidCredentials, was auch immer.
Svish
@Svish - Wenn Sie jedoch versuchen, überhaupt keine Hinweise auf den Grund für den Fehler zu geben, ist die Rückgabe nullgenau die am wenigsten hilfreiche Antwort. Fast alles andere könnte möglicherweise verwendet werden, um etwas über das System herauszufinden. Der Grund, warum sich OP beschwerte, war, dass die nullRückgabe nicht nur nichts erklärte, sondern auch nicht hilfreich war. Das ist das bewusste Ziel ... absolut nichts zu sagen und nicht hilfreich zu sein. Mission aus meiner Sicht erfüllt.
OldCurmudgeon
Nun, das mag so sein, aber ich würde immer noch sagen, dass es schlecht ist, das zu tun. Zumindest innerhalb eines Systems. An den Rändern, an denen der Endbenutzer Dinge sieht, kann ich dem sicher zustimmen. Aber innerhalb des Systems sind wir Entwickler die Benutzer, und warum in aller Welt wollen wir die Dinge für uns selbst verwirrender machen? Als ob die Entwicklung von Software nicht schon schwer genug wäre ...
Svish
1
Und mit dem Anmeldebeispiel würde ich sagen, dass es für die Benutzererfahrung schlecht ist, nicht wenigstens etwas darüber zu sagen , warum nichts passiert zu sein schien, als sie (dachten, sie) ihre Anmeldeinformationen eingegeben haben. Wenn die Seite nur aktualisiert wird und mein Anmeldeversuch einfach ignoriert wurde, gehe ich davon aus, dass etwas mit dem System nicht stimmt und nicht, dass das, was ich eingegeben habe, falsch war.
Svish
-2

Ich denke, return null ist unfreundlich. Wenn der Client diese Methode aufruft und null zurückgibt, weiß der Client nicht, was passiert ist und warum er null zurückgegeben hat. Wir sollten also eine sinnvolle Ausführung ausführen und eine Dokumentation bereitstellen, um diese Ausführung zu beschreiben.

Mark xie
quelle