Le restrizioni di sicurezza possono causare la restituzione di un servizio null o il lancio di un'eccezione? [chiuso]

11

Sono un po 'in disaccordo con uno sviluppatore più esperto su questo problema, e mi chiedo cosa ne pensino gli altri; il nostro ambiente è Java, EJB 3, servizi, ecc.

Il codice che ho scritto chiama un servizio per ottenere cose e creare cose. Il problema che ho riscontrato è che ho avuto eccezioni di puntatori nulli che non avevano senso. Ad esempio, quando chiedo al servizio di creare un oggetto, ottengo null; quando provo a cercare un oggetto con un ID valido noto, ottengo null. Ho passato un po 'di tempo a cercare di capire cosa c'era di sbagliato nel mio codice; dal momento che sono meno esperto di solito ritengo di aver fatto qualcosa di sbagliato, ma si scopre che la ragione per i ritorni nulli è stata la sicurezza. Se l'utente principale che utilizza il mio servizio non ha le autorizzazioni giuste per il servizio di destinazione, restituisce semplicemente null. Anche la maggior parte degli altri servizi qui non sono ben documentati, quindi a quanto pare questo è solo qualcosa che devi sapere.

Questo è piuttosto confuso come uno sviluppatore che scrive codice che interagisce con il servizio. Avrebbe molto più senso per me se il servizio fosse un'eccezione che mi dicesse che l'utente non aveva le autorizzazioni appropriate per caricare questa cosa o per creare quella cosa; Vorrei quindi sapere immediatamente perché il mio servizio non funzionava come previsto.

Lo sviluppatore più esperto che ha scritto il servizio ha sostenuto che la richiesta dei dati non è una condizione di errore e che le eccezioni dovrebbero essere generate in una condizione di errore, non quando l'utente non ha accesso ai dati. Questi dati sono spesso consultati in una GUI e per quegli utenti senza le giuste autorizzazioni, queste cose semplicemente "non esistono". Quindi, in breve: chiedere non è sbagliato, quindi nessuna eccezione. Ottieni metodi restituisce null perché a quegli utenti quelle cose "non esistono". Creare metodi restituisce null quando all'utente non è stato permesso di creare quella cosa.

Questa è normale e / o buona pratica? Preferisco usare le eccezioni perché trovo molto più facile sapere cosa sta succedendo. Quindi, ad esempio, preferirei anche lanciare una NotFoundException se hai richiesto un oggetto con un ID non valido, piuttosto che restituire null.

    
posta Svish 24.11.2011 - 14:48
fonte

10 risposte

20

Exceptions should only be thrown when there is an error and asking for a thing is not an error.

Chiedere una cosa potrebbe non essere un errore, ma non avere permessi per qualcosa che hai chiesto è sicuramente una sorta di errore. Le eccezioni sono un modo alternativo di riportare condizioni eccezionali, da utilizzare al posto di valori di ritorno speciali (come null , che, come hai scritto, non è di alcun aiuto se ci sono > 1 possibili motivi per cui le cose potrebbero andare storte ( anche se ora c'è esattamente 1 possibile motivo, ci potrebbero essere 2 possibili motivi nella prossima versione, quindi usare null come valore di ritorno che indica il fallimento potrebbe dipingersi nell'angolo)). Se il servizio non riporta in alcun modo perché non farà ciò che hai chiesto, allora è decisamente un cattivo design.

Se utilizzare un valore di ritorno speciale (ad esempio, gli interi negativi sono utili per le funzioni che normalmente restituiscono un intero non negativo), un'eccezione, un gestore di errori globale o un logger ecc., è un dettaglio di implementazione alla fine. La scelta dipende dalla lingua, dalla situazione, dalle convenzioni, ed è anche una questione di gusti. Il punto principale è che ci dovrebbe essere alcuni modo diretto per scoprire perché qualcosa non funziona. Altrimenti la tua unica opzione è di spazzare via con diverse opzioni e qualsiasi altra cosa per scoprire cosa si correla al comportamento della scatola nera, ed è tempo perso.

String.substring() genera un IndexOutOfBoundsException se l'indice è fuori limite. Non riesco a pensare ad alcun vantaggio nel restituire null , anche se - filosoficamente - si potrebbe sostenere che un String non contenga nulla al di fuori dei suoi limiti, quindi null sarebbe quindi un valore di ritorno logico. Essere logico-filosofici ed essere pratici sono ovviamente due animali diversi.

    
risposta data 24.11.2011 - 15:05
fonte
5

Dipende da cosa è il contratto. Se il tuo contratto dice che puoi richiedere qualcosa che non esiste, dovrebbe dire cosa succede (null o null oggetto).

D'altro canto, se il tuo contratto dice che dovresti chiamare prima un metodo diverso ( DoesSomethingExist() ) e poi chiamare il metodo Get , allora il tuo contratto potrebbe dire che puoi solo ottenere cose che esistono e lanciare un'eccezione se non lo fanno. Il messaggio di eccezione potrebbe indicare qualcosa come "Assicurati di chiamare DoesSomethingExist() prima", che è un utile messaggio di errore.

    
risposta data 24.11.2011 - 15:11
fonte
4

Non esiste un'unica risposta valida per tutti alla domanda. Se utilizzare le eccezioni o restituire null dipende dalla situazione.

Invece di guardare questo da un punto di vista dogmatico, guarda l'interfaccia come interfaccia utente . Le interfacce utente dovrebbero essere utilizzabili . Quindi, indipendentemente dalle tue opinioni sul modo "giusto" di fare qualcosa, scegli il metodo più utilizzabile dal punto di vista di qualcuno che usa la tua interfaccia.

Se il chiamante deve sapere perché non viene restituito un oggetto, è appropriata un'eccezione. Se, tuttavia, il concetto generale è "se non si dispone dell'autorizzazione, non esiste", il nulla è accettabile.

Specificamente nel tuo caso, direi che i null sono perfettamente accettabili per la ricerca di un elemento se prima è richiesto al chiamante di accedere o connettersi al server. Questo è il momento in cui ti verrebbe detto che fai o non hai il permesso. Una volta superato il gate è ragionevole che quando cerchi qualcosa che non hai il permesso di vedere (o che nemmeno lo sappia che esiste), dovresti ottenere un null.

Se, d'altra parte, non si dispone di una connessione iniziale o di una fase di accesso, un'eccezione ha senso. Se il chiamante conosce un elemento esistente e non lo sta recuperando, l'API non è utile per restituire un valore null.

Per creare un oggetto, tuttavia, questa è una storia diversa. Presumibilmente ci potrebbero essere molte ragioni per cui fallire - nessuna autorizzazione, parametri errati, memoria insufficiente del server, ecc. Se lo sviluppatore ha un valore nullo per tutte queste condizioni, non ha modo di determinare una corretta linea di condotta .

Quindi, per rispondere alla domanda, chiediti quale sia la soluzione più utilizzabile dal punto di vista di qualcuno che utilizza il servizio. Può essere che il modo in cui tu stai usando sia atipico, e per il caso più comune un null è la risposta giusta.

Quindi, non entrare in una guerra religiosa per questo, decidi cosa è giusto per questo particolare problema.

    
risposta data 24.11.2011 - 15:03
fonte
3

Sicuramente penso che sia un cattivo design . Il puntatore Null non è una risposta valida per me e può essere difficile da gestire.

Se l'utente prova a connettere un servizio senza le credenziali appropriate, dovrei rispondere con una risposta chiara e concisa. La risposta potrebbe essere un'eccezione o un oggetto speciale ma non nullo.

Dovresti lasciare la risposta nulla quando il collegamento di rete è interrotto o altri malfunzionamenti critici imprevisti.

Inoltre, il tempo speso per capire perché hai ottenuto un null è un argomento strong. Ogni pezzo di codice dovrebbe essere facile da capire e da usare. Avere un valore nullo non è il caso.

    
risposta data 24.11.2011 - 14:56
fonte
3

Tenendo presente il buon design del software, dovresti pensare alla vita del tuo progetto.
Restituendo null , come è stato detto, non fornisci alcuna informazione al cliente. Guarda cosa ti è successo, all'inizio non ti rendi conto di dove fosse il problema. Inoltre, se non viene fornita alcuna documentazione, questo è un disastro.

Lanciando un'eccezione, puoi dire cosa è andato storto. Puoi anche personalizzare il testo visualizzato per essere più specifico, se lo desideri.

D'altro canto, restituendo null fai in modo che il client indaga su cosa sta succedendo.

Inoltre, ti sei reso conto che c'era un problema perché hai ottenuto altrove NullPointerException . Ora immagina di non memorizzare il ritorno di quella funzione ... Sarai costretto a circondare ogni chiamata a quella funzione con un blocco if else ...

Dal mio punto di vista, restituire null è una cattiva pratica.

    
risposta data 24.11.2011 - 16:32
fonte
2

The more experienced developer who wrote the service argued that asking for the data is not an error condition, and that exceptions should only be thrown in an error condition, not when the user doesn't have access to the data.

Dal mio punto di vista, questo non ha senso.

Interrogare per i dati senza permesso dovrebbe comportare un'eccezione, poiché è un risultato inatteso - per ottenere risultati senza accesso appropriato.

Analogy : il responsecode per GET senza autorizzazione non è 200 ok senza dati, in realtà è 401 Unauthorized .

    
risposta data 09.09.2015 - 23:31
fonte
1

Restituire null non è grandioso. Non ti dice nulla. Per fare il tuo esempio, se un'app sta cercando di guardare qualcosa e la risposta è nullo per entrambi i problemi di sicurezza e se l'elemento non esiste, allora come fai a distinguere tra i due?

Una risposta significativa può consentire all'applicazione di fare scelte logiche su cosa fare in seguito o su come risolvere i problemi.

    
risposta data 24.11.2011 - 14:58
fonte
1

Se la causa principale è un utente non autenticato, preferisco una risposta HTTP 401 difficile, magari con un reindirizzamento a una bella pagina di messaggi (e una notifica a qualcuno che se ne preoccupa). Le cause relative all'autorizzazione sono più caso per caso; ci sono argomenti per la restituzione di errori HTTP (403, per esempio) e argomenti per la restituzione di codici / messaggi speciali ben formati nella risposta del servizio.

Le eccezioni dovrebbero essere utilizzate solo in circostanze eccezionali e significa che qualcosa è andato storto. Non sono d'accordo sul fatto che dovrebbero essere sovraccaricati per significare "non consentito". (Lo stesso vale per il valore di ritorno nullo: non sono d'accordo sul fatto che dovrebbe essere usato per indicare "non consentito".)

    
risposta data 24.11.2011 - 15:06
fonte
0

Per giocare ai diavoli avvocato cercherò di prendere il lato di restituire null.

Secondo me c'è solo una situazione in cui questo tipo di risposta è quasi accettabile e cioè, come in questo caso, quando è coinvolta la sicurezza.

È molto facile dare per sbaglio dettagli del tuo sistema che persone non autorizzate dovrebbero non sapere. Questo dovrebbe essere evitato.

Prendi, ad esempio, un controllo di nome utente e password. Restituire un errore "Nome utente non trovato" e un errore "Password errata" come codici di errore separati ti aprirebbero ovviamente a seri problemi di sicurezza poiché qualcuno potrebbe prima cercare un nome utente valido e quindi cercare una password. Restituire un generico "Nome utente / password non valido" sarebbe un'opzione migliore.

Quindi, in questo caso specifico direi che è quasi ok per restituire null ma sono d'accordo, sarebbe molto spiacevole lavorare con

.

    
risposta data 29.11.2011 - 17:20
fonte
-2

Penso che return n sia ostile, quando il client richiama questo metodo e restituisce null, il client non sa cosa sia successo e perché restituisce null. Quindi dovremmo fare l'execption che ha senso e fornire una documentazione per descriverla.

    
risposta data 25.11.2011 - 02:40
fonte

Leggi altre domande sui tag