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

25

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

Sull'orlo di aggiungere un vero framework e codice di sicurezza al nostro progetto di riscrittura delle applicazioni legacy (che finora mantiene pressoché il codice di sicurezza legacy e la convalida dei dati), mi chiedo nuovamente su quanto dovrebbe Convalido, dove, ecc.

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

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

  • Lato client di primo livello (browser): convalida minima, solo regole invariabili (campo email obbligatorio, deve selezionare un elemento e simili); utilizzo di convalida aggiuntiva come "tra 6 e 20 caratteri" meno frequente, in quanto ciò aumenta il lavoro di manutenzione sulle modifiche (può essere aggiunto una volta che il codice aziendale è stabile);

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

  • 2 ° livello (livello aziendale): validazione solida, non meno; dati in ingresso, intervalli, valori, controllo dello stato interno se il metodo non può essere chiamato in qualsiasi momento, ruoli / permessi utente e così via; utilizzare il minor numero possibile di dati di input dell'utente, recuperarlo di nuovo dal database, se necessario; se consideriamo anche i dati del database recuperati come input, lo convaliderei solo se alcuni dati specifici sono inaffidabili o danneggiati sul DB - la tipizzazione strong fa la maggior parte del lavoro qui, IMHO;

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

  • il database (modello dati): deve essere altrettanto pensato, strong e auto-attuante da evitare il più possibile dati errati e corrotti sul DB, con buone chiavi primarie, chiavi esterne, vincoli, tipo di dati / lunghezza / dimensione / precisione e così via - Lascio i trigger fuori da questo, poiché hanno una loro discussione privata.

So che la convalida dei dati in anticipo è buona e dal punto di vista delle prestazioni, ma la convalida dei dati ripetuta è un processo noioso e ammetto che la convalida dei dati è piuttosto fastidiosa. Ecco perché così tanti programmatori lo saltano o lo fanno a metà strada. Inoltre, ogni convalida duplicata è un possibile errore se non sono sincronizzati tutte le volte. Queste sono le ragioni principali per le quali oggi preferisco lasciare la maggior parte delle convalide al livello aziendale, a scapito di tempo, larghezza di banda e CPU, eccezioni gestite caso per caso.

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

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

Grazie!

Modifica: ulteriori chiarimenti sul terzo livello.

    
posta mdrg 02.06.2011 - 17:04
fonte

5 risposte

16

La tua convalida deve essere coerente. Pertanto, se un utente immette 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 che l'inserimento di una pagina di dati apparentemente correttamente solo per essere detto dopo un significativo viaggio di andata e ritorno nel database che qualcosa non andava. Questo sarebbe particolarmente vero se fossi inciampato nella convalida di alcuni client nel processo.

Devi avere la convalida a vari livelli mentre li stai esponendo e potenzialmente non hai alcun controllo su chi li chiama. Quindi è necessario organizzare (per quanto possibile) che la convalida venga definita in un unico posto e chiamata da dove è necessario. Il modo in cui questo è organizzato dipenderà dalla tua lingua e dalla tua struttura. In Silverlight (ad esempio) è possibile definirlo sul lato server e con gli attributi appropriati verrà copiato sul lato client per utilizzarlo.

    
risposta data 02.06.2011 - 17:12
fonte
9

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

  • Presentazione / UI
    • convalida dell'input semplice
    • non procedere se l'input è nel formato errato
    • "gate" richieste del client al server per ridurre i viaggi di andata e ritorno, per una migliore usabilità e riduzione della larghezza di banda / tempo
  • Logic
    • business logic e autorizzazione
    • non permettere agli utenti di fare cose che non sono autorizzati a fare
    • gestire le proprietà "derivate" e indicare qui (cose che sarebbero denormalizzate nel database)
  • Dati
    • il livello di integrità dei dati essenziali
    • assolutamente rifiutare di memorizzare qualsiasi junk
    • il DB stesso impone i formati dei dati (int, date, ecc.)
    • utilizza i vincoli del database per garantire relazioni corrette

La risposta ideale a questo sarebbe un sistema che consente di definire i vincoli su tutti e tre i livelli in un unico punto. Ciò implicherebbe una certa generazione di codice per SQL e almeno alcune convalide basate sui dati per client e server.

Non so se ci sia un proiettile d'argento qui ... ma dato che sei sulla JVM suggerirei di guardare a Rhino almeno di condividere il codice di convalida JavaScript tra client e server. Non scrivere la convalida dell'input due volte.

    
risposta data 02.06.2011 - 18:20
fonte
6

•3rd tier (data layer/DAL/DAO): never believed much validation is needed here, as only the business layer is supposed to access the data (validate maybe on some case like "param2 must not be null if param1 is true").

Questo è così sbagliato. Il posto più importante per avere la convalida è nel database stesso. I dati sono quasi sempre influenzati da oltre l'applicazione (anche quando pensate che non lo sarà) ed è irresponsabile, nel migliore dei casi, non inserire controlli adeguati nel database. C'è più 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 sia riuscito a far rispettare le regole di integrità a livello di database che contenevano buoni dati (e ho visto i dati in letteralmente migliaia di database).

Lo dice meglio di me: link

    
risposta data 02.06.2011 - 17:46
fonte
2

Tutto quanto sopra presuppone che sviluppatori e manutentori siano perfetti e scrivano un codice perfetto che funzioni sempre perfettamente. Le versioni future del software conoscono tutte le ipotesi che hai fatto e mai documentate, e gli utenti e gli hacker che inseriscono i dati nel sistema in modi che non avresti mai immaginato.

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

Disegna circoli di confine intorno alle cose, identifica le modalità di errore che protegge e implementa un livello appropriato di controllo per quel confine. Ad esempio, il tuo database non dovrebbe mai vedere dati non validi, ma come potrebbe accadere e cosa succederebbe se lo facesse? 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. Uno spesso muro è considerato di scarsa sicurezza. La convalida dei dati deve essere considerata allo stesso modo.

    
risposta data 03.06.2011 - 03:10
fonte
1

Due brevi regole generali per la convalida:

Se stai per chiamare qualcosa che non garantisce che restituirà qualcosa (errore, eccezione) per dirti dell'input non valido in un modo che puoi ritrasferire al tuo chiamante, validarlo.

Se hai intenzione di fare qualcos'altro con i dati (prendere decisioni, fare matematica, memorizzarlo, ecc.), validarlo.

    
risposta data 02.06.2011 - 21:37
fonte