Validação de entrada de dados - Onde? Quantos? [fechadas]


28

A validação de entrada de dados sempre foi uma luta interna para mim.

À beira de adicionar uma estrutura e um código de segurança reais ao nosso projeto de reescrita de aplicativos herdados (que até agora mantém praticamente o código de segurança herdado e a validação de dados), estou pensando novamente sobre quanto devo validar, onde etc.

Nos meus 5 anos como desenvolvedor profissional de Java, criei e refinei minhas regras pessoais para validação de entrada de dados e medidas de segurança. Como gosto de melhorar meus métodos, alguns gostariam de ouvir algumas idéias de vocês. Regras e procedimentos gerais são bons e específicos de Java também.

Resumidas, estas são minhas diretrizes (expostas em um estilo de aplicativo da web de três camadas), com breves explicações:

  • Lado do cliente da 1ª camada (navegador): validação mínima, apenas regras invariáveis ​​(campo obrigatório de e-mail, deve selecionar um item e similares); uso de validação adicional como "entre 6 e 20 caracteres" menos frequente, pois isso aumenta o trabalho de manutenção nas alterações (pode ser adicionado quando o código comercial estiver estável);

  • Lado do servidor de 1ª camada (manipulação de comunicação na web, "controladores"): não tenho uma regra para esta, mas acredito que apenas os erros de manipulação de dados e montagem / análise devem ser tratados aqui (o campo de aniversário não é uma data válida); adicionar validação adicional aqui facilmente o torna um processo realmente chato;

  • 2º nível (camada de negócios): validação sólida, nada menos; formato de dados de entrada, intervalos, valores, verificação interna do estado se o método não pode ser chamado a qualquer momento, funções / permissões do usuário e assim por diante; use o mínimo possível de dados de entrada do usuário, recupere-os novamente do banco de dados, se necessário; se considerarmos os dados recuperados do banco de dados como entrada também, eu apenas os validaria se alguns dados específicos forem confiáveis ​​ou corrompidos o suficiente no banco de dados - a digitação forte faz a maior parte do trabalho aqui, IMHO;

  • 3ª camada (camada de dados / DAL / DAO): nunca se acreditou que muita validação fosse necessária aqui, pois apenas a camada de negócios deveria acessar os dados (valide talvez em alguns casos como "param2 não deva ser nulo se param1 for verdadeiro"); observe, no entanto, que quando eu quero dizer "aqui", quero dizer "código que acessa o banco de dados" ou "métodos de execução SQL", o próprio banco de dados é completamente o oposto;

  • o banco de dados (modelo de dados): precisa ser tão bem pensado, forte e auto-impositivo quanto evitar dados incorretos e corrompidos no banco de dados, tanto quanto possível, com boas chaves primárias, chaves estrangeiras, restrições, tipo / comprimento / tamanho de dados / precision e assim por diante - estou deixando os gatilhos fora disso, pois eles têm sua própria discussão particular.

Sei que a validação antecipada de dados é agradável e em termos de desempenho, mas a validação repetida é um processo chato e admito que a validação de dados em si é bastante irritante. É por isso que muitos codificadores pulam ou fazem isso até a metade. Além disso, toda validação duplicada é um bug possível se não estiverem sincronizadas o tempo todo. Esses são os principais motivos pelos quais hoje em dia prefiro deixar a maioria das validações até a camada de negócios, em detrimento do tempo, largura de banda e CPU, exceções tratadas caso a caso.

Então, o que você pensa sobre isso? Opiniões opostas? Você tem outros procedimentos? Uma referência a esse tópico? Qualquer contribuição é válida.

Nota: se você está pensando na maneira Java de fazer as coisas, nosso aplicativo é baseado em Spring com Spring MVC e MyBatis (desempenho e modelo de banco de dados incorreto excluem as soluções ORM); Pretendo adicionar o Spring Security como nosso provedor de segurança mais o JSR 303 (Hibernate Validator?)

Obrigado!


Editar: algum esclarecimento extra na 3ª camada.


Meu conselho é estudar como o Hibernate Validator funciona. Não achei o JSR 303 útil, pois a validação entra em vigor durante a persistência, enquanto algumas das minhas regras precisavam ser aplicadas muito antes da persistência, pois eu tinha regras de negócios que dependiam da validação básica. Na minha opinião, ele funciona para um modelo muito fechado; talvez eu estivesse usando incorretamente, mas nunca encontrei alguém com experiências diferentes das minhas.
Vineet Reynolds

Vinet Reynolds Eu já o usei para validação de formulários com o Spring MVC, é realmente uma ótima combinação. Recebo validação do lado do servidor com mensagens refinadas com pouco ou nenhum esforço, erro apropriado exibido ao usuário. Ainda estou para testá-lo inteiramente em objetos do lado do servidor, sem ter certeza das vantagens. Dê uma olhada neste post de exemplo, foi assim que eu o usei: codemunchies.com/2010/07/…
mdrg

2
colocar muita validação. EveryWhere maldita essas entradas do usuário @ #! ! @@!
Chani

Respostas:


17

Sua validação deve ser consistente. Portanto, se um usuário digitar alguns dados no formulário da web que sejam determinados como válidos, não deverá ser rejeitado pela camada do banco de dados devido a alguns critérios que você não implementou no lado do cliente.

Como usuário, nada seria mais irritante do que digitar uma página cheia de dados aparentemente corretamente, apenas para ser informado após uma ida e volta significativa ao banco de dados que algo estava errado. Isso seria particularmente verdadeiro se eu tivesse ativado uma validação de cliente no processo.

Você precisa ter a validação em vários níveis, pois os expõe e, potencialmente, não tem controle sobre quem os chama. Portanto, você precisa providenciar (na medida do possível) que sua validação seja definida em um local e chamada de onde quer que seja necessária. Como isso é organizado depende do seu idioma e estrutura. No Silverlight (por exemplo), você pode defini-lo no lado do servidor e, com atributos adequados, ele será copiado no lado do cliente para uso no local.


2
+1 Absolutamente. Eu ia dizer a mesma coisa sobre o ASP.NET MVC, mas você me venceu. :) Realmente, só precisamos da validação no local para garantir que um sistema permaneça em um estado válido. O restante da validação, como o lado do cliente, deve aprimorar a usabilidade e o tempo perdido para o usuário, de modo que esse deve ser o foco principal. Consistência é a chave.
Ryan Hayes

2
Sobre a "viagem de ida e volta", não vejo problema desde que a página seja recarregada com mensagens de erro apropriadas e todos os campos preenchidos com o que você digitou antes (a maioria das interfaces fica aquém desse último detalhe). Se demorar muito para voltar com os erros, é um candidato à validação adicional do lado do cliente.
mdrg

E, com certeza, se a validação puder ser replicada facilmente no aplicativo, não há motivo para desperdiçar isso. No lado do servidor, é fácil, mas no lado do cliente, sem essas ferramentas de validação, como a que você mencionou, fica muito frustrante (ou seja: escrever muito código de validação JS, exatamente como o que você escreveu no servidor) .
mdrg

10

Em um sistema relacional, eu o vejo como uma abordagem em três camadas. Cada camada é restrita pelas abaixo:

  • Apresentação / UI
    • validação de entrada simples
    • não continue se a entrada estiver no formato errado
    • cliente "gate" solicita ao servidor que reduza as viagens de ida e volta, para melhor usabilidade e largura de banda / tempo reduzidos
  • Lógica
    • lógica e autorização de negócios
    • não permita que os usuários façam coisas que eles não têm permissão para fazer
    • manipular propriedades "derivadas" e indicar aqui (itens que seriam desnormalizados no banco de dados)
  • Dados
    • a camada essencial de integridade de dados
    • absolutamente se recusam a armazenar qualquer lixo
    • o próprio banco de dados impõe formatos de dados (int, data etc.)
    • use restrições de banco de dados para garantir relacionamentos adequados

A resposta ideal para isso seria um sistema que permite definir as restrições nas três camadas em um único local. Isso envolveria alguma geração de código para SQL e pelo menos alguma validação orientada a dados para o cliente e o servidor.

Não sei se há alguma bala de prata aqui ... mas, como você está na JVM, sugiro que procure no Rhino para compartilhar pelo menos o código de validação JavaScript entre o cliente e o servidor. Não escreva sua validação de entrada duas vezes.


Vou dar uma olhada no Rhino. Se ele puder se integrar de alguma forma com a validação de formulário do Spring MVC, muito melhor.
mdrg

8

• Terceira camada (camada de dados / DAL / DAO): nunca se acreditou que muita validação fosse necessária aqui, pois apenas a camada de negócios deveria acessar os dados (valide talvez em alguns casos como "param2 não deva ser nulo se param1 for verdadeiro") .

Isto é tão errado. O local mais importante para a validação é no próprio banco de dados. Os dados quase sempre são afetados por mais do que o aplicativo (mesmo quando você acha que não será) e é irresponsável, na melhor das hipóteses, não colocar controles adequados no banco de dados. Há mais perda de integridade dos dados de uma decisão de não fazer isso do que qualquer outro fator. A integridade dos dados é fundamental para o uso a longo prazo do banco de dados. Eu nunca vi nenhum banco de dados que falhou em impor regras de integridade no nível do banco de dados que continham bons dados (e eu os vi em literalmente milhares de bancos de dados).

Ele diz isso melhor do que eu: http://softarch.97things.oreilly.com/wiki/index.php/Database_as_a_Fortress


Concordo com a última parte deste artigo, acho que não me deixei claro nesta parte. Atualizei a pergunta com mais detalhes. Obrigado!
mdrg

2

Todos os itens acima assumem que desenvolvedores e mantenedores são perfeitos e escrevem códigos perfeitos que sempre funcionam perfeitamente. As futuras versões de software conhecem todas as suposições que você fez e nunca documentou, além de usuários e hackers que colocam dados no sistema de maneiras que você nunca imaginou.

Certamente, validação demais é uma coisa ruim, mas supondo que programas, redes e sistemas operacionais sejam perfeitos, os hackers não passarão pelo firewall, os DBAs não "ajustarão" manualmente o banco de dados provavelmente é pior.

Desenhe círculos de limite em torno das coisas, identifique os modos de falha contra os quais está protegendo e implemente um nível apropriado de verificação desse limite. Por exemplo, seu banco de dados nunca deve ver dados inválidos, mas como isso poderia acontecer e se acontecer? Quem é seu usuário, qual é o custo da falha?

Estudar modelos de segurança do mundo físico, a segurança deve estar em camadas, como uma cebola. Uma parede espessa é considerada falta de segurança. A validação de dados deve ser considerada da mesma maneira.


1

Duas breves regras gerais para validação:

Se você ligar para algo que não garanta que retornará algo (erro, exceção) para informar sobre entrada inválida de uma maneira que você possa retornar ao seu chamador, valide-a.

Se você quiser fazer mais alguma coisa com os dados (tomar decisões, fazer contas, armazená-los etc.), valide-os.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.