Validación de entrada de datos: ¿dónde? ¿Cuánto cuesta? [cerrado]

28

La validación de entrada de datos siempre fue una lucha interna para mí.

A punto de agregar un marco de seguridad real y un código a nuestro proyecto de reescritura de aplicaciones heredadas (que hasta ahora mantiene el código de seguridad heredado y la validación de datos heredados), me pregunto nuevamente cuánto debería validar, donde, etc.

Durante mis 5 años como desarrollador profesional de Java, creé y perfeccioné mis reglas personales para la validación de entrada de datos y medidas de seguridad. Como me gusta mejorar mis métodos, me gustaría que algunos escuchen algunas ideas de ustedes. Las reglas y procedimientos generales están bien, y los específicos de Java también.

En resumen, estas son mis pautas (expuestas en un estilo de aplicación web de 3 niveles), con breves explicaciones:

  • 1.o nivel del lado del cliente (navegador): validación mínima, solo reglas invariables (campo de correo electrónico obligatorio, debe seleccionar un elemento y similares); uso de validación adicional como "entre 6 y 20 caracteres" menos frecuente, ya que esto aumenta el trabajo de mantenimiento en los cambios (se puede agregar una vez que el código comercial es estable);

  • Lado del servidor de primer nivel (manejo de comunicación web, "controladores"): no tengo una regla para este, pero creo que solo se deben manejar aquí los errores de manipulación de datos y ensamblaje / análisis (el campo de cumpleaños no es una fecha válida); agregar más validación aquí fácilmente lo convierte en un proceso realmente aburrido;

  • 2do nivel (capa empresarial): validación sólida como una roca, nada menos; formato de datos de entrada, rangos, valores, verificación interna del estado si el método no se puede llamar en cualquier momento, roles / permisos del usuario, etc. use la menor cantidad posible de datos de entrada del usuario, recupere nuevamente de la base de datos si es necesario; si consideramos también los datos recuperados de la base de datos como entrada, solo los validaría si se sabe que algunos datos específicos no son confiables o están lo suficientemente corruptos en la base de datos: la escritura fuerte hace la mayor parte del trabajo aquí, en mi humilde opinión;

  • 3er nivel (capa de datos / DAL / DAO): nunca creí que se necesitara mucha validación aquí, ya que solo se supone que la capa empresarial tiene acceso a los datos (validar quizás en algún caso como "param2 no debe ser nulo si param1 es verdadero"); observe, sin embargo, que cuando me refiero a "aquí" me refiero a "código que accede a la base de datos" o "métodos de ejecución de SQL", la base de datos en sí es completamente lo contrario;

  • la base de datos (modelo de datos): debe ser tan bien pensada, fuerte y autoejecutable como para evitar datos incorrectos y corruptos en la base de datos tanto como sea posible, con buenas claves primarias, claves externas, restricciones, tipo / longitud / tamaño de datos / precisión y así sucesivamente: estoy dejando de lado los desencadenantes, ya que tienen su propia discusión privada.

Sé que la validación de datos temprana es buena y en cuanto al rendimiento, pero la validación de datos repetida es un proceso aburrido, y admito que la validación de datos en sí misma es bastante molesta. Es por eso que tantos codificadores lo omiten o lo hacen a mitad de camino. Además, cada validación duplicada es un posible error si no están sincronizados todo el tiempo. Esas son las principales razones por las que hoy en día prefiero dejar que la mayoría de las validaciones lleguen a la capa empresarial, a expensas del tiempo, el ancho de banda y la CPU, excepciones manejadas caso por caso.

Entonces, ¿qué piensas sobre esto? Opiniones opuestas? ¿Tienes otros procedimientos? ¿Una referencia a ese tema? Cualquier contribución es válida.

Nota: si está pensando en la manera Java de hacer las cosas, nuestra aplicación está basada en Spring con Spring MVC y MyBatis (el rendimiento y el modelo de base de datos incorrecto descartan las soluciones ORM); Planeo agregar Spring Security como nuestro proveedor de seguridad más JSR 303 (¿Validador de Hibernación?)

¡Gracias!


Editar: algunas aclaraciones adicionales en la tercera capa.

mdrg
fuente
Mi consejo es estudiar cómo funciona Hibernate Validator. No he encontrado que JSR 303 sea útil, ya que la validación entra en vigencia durante la persistencia, mientras que algunas de mis reglas tuvieron que aplicarse mucho antes de la persistencia, ya que tenía reglas comerciales que se basaban en la validación básica. En mi opinión, funciona para un modelo muy cerrado; tal vez lo estaba usando incorrectamente, pero nunca encontré a nadie con experiencias diferentes a las mías.
Vineet Reynolds
@Vineet Reynolds Ya lo usé para la validación de formularios con Spring MVC, es una gran combinación. Obtengo la validación del lado del servidor con mensajes específicos con poco o ningún esfuerzo, se muestra el error apropiado al usuario. Todavía tengo que probarlo completamente en objetos del lado del servidor, no estoy seguro de las ventajas. Eche un vistazo a esta publicación de muestra, así es como la usé: codemunchies.com/2010/07/…
mdrg
2
Poner demasiada validación. EveryWhere maldita esas entradas de usuario @ #! ! @@!
Chani

Respuestas:

17

Su validación debe ser consistente. Entonces, si un usuario ingresa algunos datos en el formulario web que se determina que es válido, la capa de base de datos no debe rechazarlo debido a algunos criterios que no implementó en el lado del cliente.

Como usuario, nada sería más molesto que ingresar una página llena de datos aparentemente correctamente solo después de un importante viaje de ida y vuelta a la base de datos que algo está mal. Esto sería particularmente cierto si hubiera tropezado con alguna validación del cliente en el proceso.

Debe tener la validación en varios niveles, ya que los está exponiendo y potencialmente no tiene control sobre quién los está llamando. Por lo tanto, debe organizar (en la medida de lo posible) para que su validación se defina en un lugar y se llame desde donde sea necesario. Cómo se arregla esto dependerá de su idioma y marco. En Silverlight (por ejemplo) puede definirlo en el lado del servidor y con los atributos adecuados se copiará en el lado del cliente para su uso allí.

ChrisF
fuente
2
+1 absolutamente. Iba a decir lo mismo sobre ASP.NET MVC, pero me ganaste. :) Realmente, solo NECESITAMOS validación en el lugar para asegurarnos de que un sistema permanezca en un estado válido. El resto de la validación, como el lado del cliente, es mejorar la usabilidad y el tiempo perdido para el usuario, por lo que ese debería ser el enfoque principal. La consistencia es la clave.
Ryan Hayes
2
Sobre el "viaje de ida y vuelta", no veo ningún problema, siempre y cuando la página se vuelva a cargar con los mensajes de error adecuados y todos los campos se llenen con lo que haya escrito anteriormente (la mayoría de las interfaces se quedan cortas en este último detalle). Si tarda demasiado en volver con los errores, entonces ese es un candidato para la validación adicional del lado del cliente.
mdrg
Y claro, si la validación se puede replicar fácilmente en la aplicación, no hay razón para desperdiciarla. En el lado del servidor es fácil, pero en el lado del cliente, sin herramientas de validación como la que mencionó, se vuelve muy frustrante (es decir, escribir mucho código de validación JS, como el que escribió en el servidor) .
mdrg
10

En un sistema relacional, lo veo como un enfoque de tres capas. Cada capa está limitada por las siguientes:

  • Presentación / UI
    • validación de entrada simple
    • no continúe si la entrada está en el formato incorrecto
    • El cliente "puerta" solicita al servidor que reduzca los viajes de ida y vuelta, para una mejor usabilidad y menor ancho de banda / tiempo
  • Lógica
    • lógica de negocios y autorización
    • no dejes que los usuarios hagan cosas que no tienen permitido hacer
    • maneje las propiedades "derivadas" y establezca aquí (cosas que se desnormalizarían en la base de datos)
  • Datos
    • la capa esencial de integridad de datos
    • absolutamente rechazar almacenar cualquier basura
    • el DB en sí mismo impone formatos de datos (int, date, etc.)
    • usar restricciones de la base de datos para garantizar relaciones adecuadas

La respuesta ideal a esto sería un sistema que le permita definir las restricciones en las tres capas en un solo lugar. Esto implicaría cierta generación de código para SQL, y al menos una validación basada en datos para el cliente y el servidor.

No sé si hay una bala de plata aquí ... pero como estás en la JVM, te sugiero que mires a Rhino para al menos compartir el código de validación de JavaScript entre el cliente y el servidor. No escriba su validación de entrada dos veces.

John Cromartie
fuente
Echaré un vistazo a Rhino. Si puede integrarse de alguna manera con la validación de formularios Spring MVC, mucho mejor.
mdrg
8

• 3er nivel (capa de datos / DAL / DAO): nunca creí que se necesitara mucha validación aquí, ya que se supone que solo la capa empresarial tiene acceso a los datos (validar tal vez en algún caso como "param2 no debe ser nulo si param1 es verdadero") .

Esto esta muy mal. El lugar más importante para tener la validación es en la propia base de datos. Los datos casi siempre se ven afectados por algo más que la aplicación (incluso cuando cree que no lo será) y, en el mejor de los casos, es irresponsable no colocar los controles adecuados en la base de datos. Hay una mayor pérdida de integridad de datos de una decisión de no hacer esto que cualquier otro factor. La integridad de los datos es crítica para el uso a largo plazo de la base de datos. Nunca he visto ninguna base de datos que no haya aplicado reglas de integridad a nivel de base de datos que contengan buenos datos (y he visto los datos en literalmente miles de bases de datos).

Lo dice mejor que yo: http://softarch.97things.oreilly.com/wiki/index.php/Database_as_a_Fortress

HLGEM
fuente
Estoy de acuerdo con lo último en este artículo, creo que no me he dejado claro en esta parte. Actualicé la pregunta con más detalles. ¡Gracias!
mdrg
2

Todo lo anterior supone que los desarrolladores y mantenedores son perfectos y escriben código perfecto que siempre se ejecuta perfectamente. Las futuras versiones de software conocen todas las suposiciones que hizo y nunca documentó, y los usuarios y piratas informáticos que introducen datos en el sistema de formas que nunca imaginó.

Claro, demasiada validación es algo malo, pero suponiendo que los programas, las redes y los sistemas operativos sean perfectos, los piratas informáticos no atravesarán su firewall, un DBA no "ajustará" manualmente la base de datos probablemente sea peor.

Dibuje círculos de límites alrededor de las cosas, identifique los modos de falla contra los que protege e implemente un nivel apropiado de verificación para ese límite. Por ejemplo, su base de datos nunca debería ver datos no válidos, pero ¿cómo podría suceder y qué sucede si lo hace? ¿Quién es su usuario, cuál es el costo del fracaso?

Estudie los modelos de seguridad física mundial, la seguridad debe estar en capas, como una cebolla. Una pared gruesa se considera poca seguridad. La validación de datos debe considerarse de la misma manera.

Mattnz
fuente
1

Dos breves reglas generales para la validación:

Si va a llamar a cualquier cosa que no garantice que devolverá algo (error, excepción) para informarle sobre una entrada no válida de una manera que pueda devolverle a la persona que llama, valídela.

Si va a hacer algo más con los datos (tomar decisiones, hacer cálculos matemáticos, almacenarlos, etc.), valídelos.

Blrfl
fuente