miércoles, 30 de junio de 2010

[ADO.NET] Hacer un Insert y no morir en el intento

Después de hacer una lectura de una base de datos, ¿qué mejor que hacer un Insert para demostrar nuestro poderoso dominio con la información? ADO.NET ofrece unas cuantas soluciones, de las cuales veremos una: empleando un SqlCommand.

Todos conocemos la instrucción Insert de SQL. Vale. Pues ya lo tenemos todo resuelto. Lo primero que tenemos que hacer es abrir la conexión y crear un string con el comando que queramos insertar. Después ejecutamos el comando, cerramos la conexión y asunto resuelto. Complicado, ¿verdad?

Aquí tenemos el código:

   1: string query = "INSERT INTO EQUIPO VALUES ('" + siglas + "','" + nombre + "')";
   2:  
   3: //usando un command builder, para evitar un sql injection como el siguiente:
   4: //insert into equipo values ('mer', 'merida fc'); delete from equipo where siglas='her';-- '');
   5:  
   6:        
   7: SqlCommand command = new SqlCommand(query, Conexion.Instancia);
   8:  
   9: if ( command.ExecuteNonQuery() == 1)
  10: {
  11:     ret = true;
  12: }

Como se aprecia, creamos un objeto SqlCommand con el string de la instrucción que queremos ejecutar (nótese que también podrían valer delete y update) junto con el SqlConnection. El SqlCommand tiene varios métodos de ejecución, entre ellos el ExecuteNonQuery que nos devuelve la cantidad de filas que se han modificado al ejecutar la instrucción. Sencilo e intuitivo, ¿verdad?

Pero lamentablemente, cada vez que alguien hace esto, Dios mata a un gatito. Esto es una muestra de una mala práctica, ya que no controla el fallo de SqlInjection. Este fallo consiste en algo normal y se produce por las siguiente causas:

  • Mal diseño: Tu capa de presentación no valida los datos.
  • Mal diseño: Tu capa de lógica no valida los datos.
  • Mal diseño: Tu aplicación provoca que se alteren datos que no debe.
  • Desastre: Borrar todo, seguridad?

En vista al código anterior, ¿que podríamos hacer en el código anterior? Un ejemplo bruto sería insertar en el campo del formulario el siguiente código:

   1: '); DELETE MASTER;

Lo cual la capa de datos, recibiría la siguiente cadena a ejecutar:

   1: INSERT INTO EQUIPO WHERE VALUES('');
   2: DELETE MASTER;
   3: ');

Sobran las palabras. ¿Qué soluciones dispone .NET para que esto no ocurra? El propio objeto SqlCommand. Anteriormente insertábamos como string toda la secuencia de comandos, con lo que la validación es muy compleja. Si en lugar de ello empleamos parámetros, estamos ganando en seguridad y estabilidad, además de la limpieza de código. La clase SqlCommand se encarga de validar los datos y evita que se pueda producir un SqlInjection. Veamos paso a paso cómo se hace:

   1: string query = "INSERT INTO EQUIPO VALUES (@siglas, @nombre)";
   2:  
   3: SqlCommand command = new SqlCommand(query, Conexion.Instancia);
   4: command.Parameters.Add(new SqlParameter("@siglas", siglas));
   5: command.Parameters.Add(new SqlParameter("@nombre", nombre));
   6:  
   7: if (command.ExecuteNonQuery() == 1)
   8: {
   9:     ret = true;
  10: }

A través del carácter @, indicamos que lo siguiente es un parámetro. Nótese que no importa siquiera el tipo de dato. Posteriormente, se crean los parámetros y se indexan internamente en el SqlCommand. Mediante SqlCommand.Parameters podemos acceder a ellos.

Como hemos visto, esto garantiza una cierta seguridad en el acceso a la BD de nuestra aplicación, además de aumentar la mantenibilidad del código y de la propia aplicación.

No hay comentarios:

Publicar un comentario