Convalida dell'input dei dati - Dove? Quanto? [chiuso]


28

La convalida dell'input dei dati è sempre stata una vera lotta interna per me.

Sul punto di aggiungere un vero framework e codice di sicurezza al nostro progetto di riscrittura di applicazioni legacy (che finora mantiene praticamente il codice di sicurezza legacy e la convalida dei dati), mi chiedo ancora quanto dovrei convalidare, dove, ecc.

Durante i miei 5 anni come sviluppatore Java professionale, ho creato e perfezionato le mie regole personali per la convalida dell'input dei dati e le misure di sicurezza. Mentre mi piace migliorare i miei metodi, vorrei che alcuni ascoltassero alcune idee da voi ragazzi. Le regole e le procedure generali vanno bene, e anche quelle specifiche di Java.

Riassumendo, queste sono le mie linee guida (esposte su uno stile di applicazione Web a 3 livelli), con brevi spiegazioni:

  • Lato client di 1 ° livello (browser): convalida minima, solo regole invariabili (campo email obbligatorio, selezionare un elemento e simili); utilizzo di convalide aggiuntive come "tra 6 e 20 caratteri" meno frequenti, poiché ciò aumenta i lavori di manutenzione sulle modifiche (può essere aggiunto una volta che il codice aziendale è stabile);

  • Lato server di 1 ° livello (gestione della comunicazione web, "controller"): non ho una regola per questo, ma credo che qui debbano essere gestiti solo gli errori di manipolazione dei dati e di assemblaggio / analisi (il campo del compleanno non è una data valida); l'aggiunta di ulteriori convalide qui rende facilmente un processo davvero noioso;

  • 2 ° livello (livello aziendale): validazione solida, nientemeno; input del formato dei dati, intervalli, valori, controllo dello stato interno se il metodo non può essere chiamato in qualsiasi momento, ruoli / autorizzazioni dell'utente e così via; utilizzare il minor numero possibile di dati di input dell'utente, recuperarli nuovamente dal database se necessario; se consideriamo anche i dati del database recuperati come input, li convaliderei solo se alcuni dati specifici sono noti per essere inaffidabili o sufficientemente corrotti sul DB - la tipizzazione forte fa la maggior parte del lavoro qui, IMHO;

  • 3 ° livello (livello dati / DAL / DAO): non ho mai creduto che fosse necessaria molta convalida, poiché solo il livello aziendale dovrebbe accedere ai dati (la convalida forse in alcuni casi come "param2 non deve essere nulla se param1 è vero"); si noti tuttavia che quando intendo "qui" intendo "codice che accede al database" o "metodi di esecuzione SQL", il database stesso è completamente l'opposto;

  • il database (modello di dati): deve essere ben pensato, forte e auto-imponente per evitare il più possibile dati errati e corrotti sul DB, con buone chiavi primarie, chiavi esterne, vincoli, tipo / lunghezza / dimensione dei dati / precision e così via: ne tralascio i trigger, poiché hanno una discussione privata.

So che la convalida precoce dei dati è buona e dal punto di vista delle prestazioni, ma la convalida ripetuta dei dati è un processo noioso e ammetto che la stessa convalida dei dati è piuttosto fastidiosa. Ecco perché così tanti programmatori lo saltano o lo fanno a metà strada. Inoltre, ogni convalida duplicata è un possibile bug se non sono sempre sincronizzati. Questi sono i motivi principali per cui preferisco oggigiorno lasciare che la maggior parte delle convalide raggiungano il livello aziendale, a scapito di tempo, larghezza di banda e CPU, eccezioni gestite caso per caso.

Allora, cosa ne pensi di questo? Opinioni opposte? Hai altre procedure? Un riferimento a tale argomento? Qualsiasi contributo è valido.

Nota: se stai pensando al modo Java di fare le cose, la nostra app è basata su Spring MVC e MyBatis (le prestazioni e il modello di database non valido escludono le soluzioni ORM); Ho intenzione di aggiungere Spring Security come nostro fornitore di sicurezza più JSR 303 (Hibernate Validator?)

Grazie!


Modifica: qualche ulteriore chiarimento sul 3 ° livello.


Il mio consiglio è di studiare come funziona Hibernate Validator. Non ho trovato JSR 303 utile, perché la convalida abbia inizio durante la persistenza, mentre alcune delle mie regole dovevano essere applicate molto prima della persistenza, poiché avevo regole commerciali che si basavano sulla convalida di base. Secondo me, funziona per un modello molto riservato; forse lo stavo usando in modo errato, ma non ho mai trovato nessuno con esperienze diverse dalle mie.
Vineet Reynolds,

@Vineet Reynolds L'ho già usato per la validazione dei moduli con Spring MVC, è davvero un'ottima combinazione. Ottengo la convalida lato server con messaggi a grana fine con poco o nessun sforzo, errore appropriato visualizzato per l'utente. Devo ancora testarlo interamente su oggetti lato server, non sono sicuro dei vantaggi. Dai un'occhiata a questo post di esempio, è così che l'ho usato: codemunchies.com/2010/07/…
mdrg

2
metti troppa convalida. Dannazione ovunque quegli input dell'utente @ #! ! @@!
Chani,

Risposte:


17

La tua convalida dovrebbe essere coerente. Quindi, se un utente inserisce alcuni dati nel modulo Web che è ritenuto valido, non dovrebbe essere rifiutato dal livello del database a causa di alcuni criteri che non sono stati implementati sul lato client.

Come utente, nulla sarebbe più fastidioso del fatto che l'immissione di una pagina di dati apparentemente corretta potesse essere raccontata solo dopo un significativo round trip nel database che qualcosa non andava. Ciò sarebbe particolarmente vero se avessi innescato un po 'di convalida del client nel processo.

Devi avere la validazione a vari livelli mentre li esponi e potenzialmente non hai controllo su chi li sta chiamando. Quindi è necessario organizzare (per quanto possibile) che la convalida sia definita in un unico posto e chiamata da dove mai è necessaria. Come sarà organizzato dipenderà dalla tua lingua e dalla tua struttura. In Silverlight (ad esempio) è possibile definirlo sul lato server e con attributi adeguati verrà copiato sul lato client per essere utilizzato lì.


2
+1 Assolutamente. Stavo per dire la stessa cosa su ASP.NET MVC, ma mi hai battuto. :) Davvero, ABBIAMO BISOGNO della validazione sul posto solo per assicurarci che un sistema rimanga in uno stato valido. Il resto della convalida, come il lato client, è di migliorare l'usabilità e il tempo perso per l'utente, quindi questo dovrebbe essere l'obiettivo principale. La coerenza è la chiave.
Ryan Hayes,

2
Riguardo al "round trip", non vedo alcun problema fino a quando la pagina viene ricaricata con i messaggi di errore corretti e tutti i campi compilati con tutto ciò che hai digitato in precedenza (la maggior parte delle interfacce non sono carenti in questo ultimo dettaglio). Se ci vuole troppo tempo per tornare indietro con gli errori, questo è un candidato per un'ulteriore convalida lato client.
mdrg,

E sicuramente, se la validazione può essere replicata facilmente attraverso l'app, non c'è motivo di sprecarla. Sul lato server è facile, ma sul lato client, senza strumenti di convalida come quello che hai citato, diventa molto frustrante (es: scrivere un sacco di codice di convalida JS, proprio come quello che hai scritto sul server) .
mdrg

10

In un sistema relazionale, lo vedo come un approccio a tre livelli. Ogni livello è vincolato da quelli di seguito:

  • Presentazione / UI
    • semplice convalida dell'input
    • non procedere se l'input è nel formato errato
    • Il client "gate" richiede al server di ridurre i viaggi di andata e ritorno, per una migliore usabilità e una larghezza di banda / tempo ridotti
  • Logica
    • logica aziendale e autorizzazione
    • non permettere agli utenti di fare cose che non possono fare
    • gestire le proprietà "derivate" e indicare qui (elementi che verrebbero denormalizzati nel database)
  • Dati
    • il livello essenziale di integrità dei dati
    • assolutamente rifiutare di conservare qualsiasi spazzatura
    • il DB stesso impone formati di dati (int, data, ecc.)
    • utilizzare i vincoli del database per garantire relazioni adeguate

La risposta ideale a questo sarebbe un sistema che ti consenta di definire i vincoli su tutti e tre i livelli in un unico posto. Ciò implicherebbe una certa generazione di codice per SQL e almeno una convalida basata sui dati per client e server.

Non so se c'è qualche proiettile d'argento qui ... ma dato che sei sulla JVM ti suggerisco di guardare Rhino per condividere almeno il codice di convalida JavaScript tra il client e il server. Non scrivere due volte la convalida dell'input.


Dò un'occhiata a Rhino. Se può integrarsi in qualche modo con la validazione del modulo Spring MVC, molto meglio.
mdrg,

8

• 3 ° livello (livello dati / DAL / DAO): non ho mai creduto che fosse necessaria molta convalida qui, poiché solo il livello aziendale dovrebbe accedere ai dati (la convalida forse in alcuni casi come "param2 non deve essere nulla se param1 è vero") .

Questo è così sbagliato. Il posto più importante per avere la convalida è nel database stesso. I dati sono quasi sempre influenzati da più dell'applicazione (anche quando si pensa che non lo sarà) ed è irresponsabile nel migliore dei casi non inserire controlli adeguati nel database. Vi è una maggiore perdita di integrità dei dati da una decisione di non farlo rispetto a qualsiasi altro fattore. L'integrità dei dati è fondamentale per l'uso a lungo termine del database. Non ho mai visto alcun database che non è riuscito a far rispettare le regole di integrità a livello di database che conteneva buoni dati (e ho visto i dati letteralmente in migliaia di database).

Lo dice meglio di me: http://softarch.97things.oreilly.com/wiki/index.php/Database_as_a_Fortress


Sono d'accordo con l'ultimo pezzo di questo articolo, immagino di non essermi chiarito in questa parte. Ho aggiornato la domanda con ulteriori dettagli. Grazie!
mdrg

2

Tutto quanto sopra presuppone che sviluppatori e manutentori siano perfetti e scrivano codice perfetto che funziona sempre perfettamente. Le future versioni del software conoscono tutti i presupposti che hai fatto e mai documentato, e gli utenti e gli hacker che inseriscono i dati nel sistema in modi che non avresti mai immaginato.

Certo, troppa convalida è una cosa negativa, ma supponendo che programmi, reti e sistemi operativi siano perfetti, gli hacker non supereranno il firewall, un DBA non "modificherà" manualmente il database probabilmente è peggio.

Disegna cerchi di confine attorno alle cose, identifica le modalità di fallimento da cui protegge e implementa un livello adeguato di controllo per quel confine. Ad esempio, il tuo database non dovrebbe mai vedere dati non validi, ma come potrebbe accadere e cosa succede se lo fa? Chi è il tuo utente, qual è il costo del fallimento?

Studia i modelli di sicurezza del mondo fisico, la sicurezza dovrebbe essere a strati, come una cipolla. Una parete spessa è considerata scarsa sicurezza. La convalida dei dati deve essere considerata allo stesso modo.


1

Due brevi regole generali per la convalida:

Se hai intenzione di chiamare qualcosa che non garantisce che restituirà qualcosa (errore, eccezione) che ti informa sull'input non valido in un modo che puoi restituire al tuo chiamante, convalidalo.

Se hai intenzione di fare qualsiasi altra cosa con i dati (prendere decisioni, fare matematica, archiviarli, ecc.), Convalidarli.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.