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.
Respostas:
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.
fonte
Em um sistema relacional, eu o vejo como uma abordagem em três camadas. Cada camada é restrita pelas abaixo:
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.
fonte
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
fonte
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.
fonte
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.
fonte