Archive for the ‘A pie de código’ Category

FindBugs

Monday, February 9th, 2009

Desde hace un tiempo venimos usando FindBugs en el proyecto en el que estoy. Para el que no lo conozca, aunque por el nombre es fácil de adivinar, se trata de una herramienta para la detección automática de posibles bugs en nuestro código.

Antes de nada decir que esta aplicación sirve para analizar código Java y que requiere una versión de la JRE (o JDK) igual o superior a la 1.5.0. No obstante, esta “limitación” es solo para correr la herramienta, ya que es capaz de detectar posibles bugs en código compilado para cualquier versión de Java.

Aunque existe una versión stand-alone de la aplicación nosotros utilizamos un plugin para Eclipse que funciona a partir de la versión 3.3. Este plugin integra las funcionalidades de FindBugs en el entorno de desarrollo, creando menús contextuales para las acciones principales y aportando una página de preferencias donde personalizar el comportamiento de la herramienta.

Lo que hace FindBugs es simple: aplicar una serie de patrones para identificar código susceptible de ser un bug. El número de estos patrones es bastante elevado y de diferente severidad. Aquí la lista completa.

Las principales categorías en qué dividen los bugs y algunos ejemplos son:

- Correctness

Código que tiene pinta de ser erroneo debido a una equivocación del programador.

Ejemplos:

* Hacer un cast imposible, que siempre va a lanzar una ClassCastException
* Aparentes bucles infinitos
* Método que define una variable que se llama igual que un atributo de la clase o superclase
* Una variable que se sabe que es null y se utiliza en un instanceof (siempre va a devolver false)

- Bad Practice

Cuando nos hemos saltado alguna de las buenas prácticas recomendadas.

Ejemplos:

* Comparar Strings utilizando == o != en vez de .equals()
* Comprobaciones en clases que definen alguno de los métodos equals() o hashCode()
* Uso de identificadores que son palabras reservadas en versiones superiores de Java
* Método suscetible de dejar abierto un Stream ante una excepción

- Dodgy

Código confuso, anómalo o escrito de forma un tanto ofuscada.

Ejemplos:
* Un método que utiliza el mismo código para dos ramas distintas de un if. Puede ser un copy/paste mal hecho.
* Código con una referencia “hardcodeada” a una ruta absoluta
* Procurar devolver un array de longitud cero antes que null.
* Implementar un interfaz que ya está siendo implementado por una superclase.
* Algún case de una sentencia switch no acaba con break y ejecutará el código del siguiente case.

Aparte de estos ejemplos mas o menos simples hay otros bastantes mas complejos (sobre todo a la hora de detectarlos en ejecución) como pueden ser:

* Un método sobrescribe a otro que se encuentra en una clase Adapter que implementa un listener de java.awt.event o javax.swing.event. Esta situación haría que el método no se llamase al ocurrir el evento.
* Una clase que extiende Servlet y utiliza atributos de clase. Como sólo se crea una instancia de cada Servlet y luego se usa en múltiples hilos de ejecución, es muy probable que esta situación de algún problema. Se recomienda usar únicamente variables locales a los métodos.

En fin, como ya os decía hay una gran cantidad de posibles errores que es capaz de detectar.

En cualquier momento podemos decirle a FindBugs que no nos avise de determinados bugs que no consideremos realmente importantes, como puede ser alguna de las buenas prácticas que sea demasiado estricta o que no nos afecte directamente ya que no estamos desarrollando código referente a alguno de esos temas.

En cuanto a cómo usarlo, o mas bien cuándo usarlo, depende de cada uno, pero mi recomendación es intentar hacer una pasada siempre que se vaya a subir código a CVS (o al sistema de control de versiones utilizado). Por ejemplo, en nuestro caso tenemos el código repartido en diferentes plugins de eclipse y, cada vez que tocamos código en uno de ellos o creamos uno nuevo, pasamos un análisis a todo el plugin para identificar posibles puntos conflictivos.

Y si aun no os he convencido del todo, un último pensamiento: ¿cuántas horas habéis perdido intentando solucionar un error para al final daros cuenta de que es que “faltaba un punto y coma aquí”?

10 Años de SQL Injection

Wednesday, December 31st, 2008

Descubro via Chema Alonso( MVP Seguridad ): Link que el pasado 25 de Diciembre se cumplieron 10 años del paper donde se expone la técnica que más adelante pasaría a llamarse SQL Injection.
Link al paper original

¿ Que no sabes qué es Sql Injection ?. Resumiendo al máximo: es una técnica para atacar una aplicación que maneja sin cuidado la generación de consultas a BD, inyectando sentencias SQL en lugar de los valores esperados.

Según la Wikipedia: Wikipedia

Por poner un ejemplo claro y clásico:

Código de LogIn en la aplicación pide Usuario y Contraseña, accede a la BD y comprueba si existe una fila en la tabla Usuarios con los datos introducidos, si es así el usuario accede a la aplicación.

Si la generación de la consulta se realiza como sigue: ( Quien no lo ha visto en todos los lenguajes de programación posibles?, salvo en LINQ, claro ;) ).

string sql = "SELECT Count(*) FROM Usuarios WHERE NombreUsuario = '" + textBoxNombreUsuario.Text + "' AND Contrasenya = '"+ textBoxContraseñaUsuario.Text + "'";

Bien, si el usuario de la aplicación, espabilado él, introduce por ejemplo, como nombre de usuario: MiUsuario’ OR 1=1 — la consulta resultante sería:

string sql = "SELECT Count(*) FROM Usuarios WHERE NombreUsuario = 'MiUsuario' OR 1=1 -- AND Contrasenya = 'cualquier cosa que ponga'";

Donde “–” en SQL comenta el resto de la línea… por lo que la consulta va a evaluar solamente las filas cuyo usuario sea ‘MiUsuario’ OR 1 sea igual a 1…. que suele serlo :)

Éste es el ejemplo más simple, recordad que SQL permite realizar operaciones en batches, separando cada consulta por ‘;’, con lo que en casos tan extremos como el anterior se pueden llegar a inyectar acciones DML tan “simples” como pueden ser DROP TABLE o DROP DATABASE: MiUsuario’ OR 1=1; DROP TABLE Usuarios —

Evidentemente para que pudieran realizarse operaciones de DML en la Base de Datos el usuario que ejecuta las consultas tendría que tener esos permisos… y no debería tenerlos, debería lo menos crearse un usuario con los menos permisos posibles para ejecutar las consultas de la aplicación y otro administrador para gestionarla … pero igualmente no se deberían crear las consultas dinámicas que estamos viendo, así que mejor verlo junto :)

A partir de aquí surgen distintas variaciones de la técnica, basándose en la información que se puede obtener de la página, como por ejemplo:

-Time-Based SqlInjection: Inyectar queries en las que si se cumple la condición que esperas se ejecuta un delay con el que poder distinguir basándonos en el tiempo de respuesta si la condición se ha cumplido o no. El ejemplo básico sería deducir una password a base de ir encontrando cada caracter, sabiendo si es válido porque cuando lo es la ejecución de la página es más lenta debido a la query inyectada. En TechNet hay un artículo, también de Chema, al respecto: link

Además de las neuronas de quien pone a prueba la aplicación, existen Tools que realizan sofisticados ataques basados en diccionarios, comparando resultados de la página, aplicando Time-Based SQL Injection… un ejemplo de herramienta puede ser :sqlpowerinjector

Bueno, me estoy extendiendo demasiado y se me acaba el año :)

Espero que con este mínimo resumen haya despertado la curiosidad de algunos y elevado el nivel de atención a la seguridad. Recordad que en general estas técnicas son totalmente independientes del lenguaje de programación y de la Base de Datos, cada uno puede tener algún agujero o característica especial, pero las técnicas generales aplican a todos.

El año que viene opinamos sobre qué hacer para evitar estas vulnerabilidades, pero las recetas mágicas no existen y siempre será necesario ser consciente de las técnicas de ataque para intentar evitarlas en lo posible.

Hotswapping en Java

Tuesday, December 9th, 2008

En el proyecto actual -una aplicación web JEE / jdk1.5 construida fundamentalmente con portlets, jsf(myfaces, tomahawk) y ejb3 que se despliega sobre JBoss Portal Server- en el que estamos colaborando nos hemos encontrado con un problema, que aunque puede que habitual en algunas ocasiones, nos está afectando en nuestras tareas de desarrollo y despliegue.

Concretamente, el problema es el tiempo que requieren las tareas de compilación, generación del archivo de despliegue (actualmente ocupa 120 megas) y el propio arranque del servidor de aplicaciones. Después de algunas “optimizaciones”, dichas tareas nos pueden llevar de 3 a 5 minutos, así que os podéis imaginar lo frustante que puede ser cuando, después de invertir ese tiempo, tratas de testear los últimos cambios que has realizado y te encuentras con un error tonto como que olvidaste negar la condición pusiste en un if o algo así… y tienes que volver a repetir todo el ciclo…

Tratando de solucionar este problema, probamos el Hotswapping (recarga de “clases” en caliente, es decir, sin necesidad de reinicar el servidor) nativo que ofrece el jdk pero, por desgracia, no conseguimos hacerlo funcionar correctamente (no tengo muy claro donde estaba el problema si en los frameworks o en el servidor de aplicaciones…) así que le dimos otra vuelta más por google y encontramos un JavaRebel:producto de pago :(, con versión de evaluación de 30 días y licencias gratuitas para desarrollos open source, que la verdad funciona bastante bien… En nuestro caso concreto pasamos de tener que construir todo el proyecto y desplegarlo (unos 3-5 minutos) a simplemente compilar las clases modificadas (10-15 segundos).

Básicamente, lo que ofrece JavaRebel es la modificación “casi completa” del bytecode “on the fly”. Aquí podéis ver una comparación con la fucionalidad ofrecida por JavaRebel frente a la ofrecida por los jdk’s actuales.

  Sun JVM HotSwap JavaRebel
Cambios en el cuerpo de los métodos SI SI
Añadir / eliminar métodos NO SI
Añadir / eliminar constructores NO SI
Añadir / eliminar atributos NO SI
Añadir / Eliminar Clases NO SI
Añadir / Eliminar anotaciones NO SI
Cambios en interfaces NO SI
Cambiar la clase padre NO NO
Añadir / Eliminar interfaces implementadas NO NO

Bueno, y que hay que hacer para utilizarlo? Pues simplemente hay que descargarse el jar de JavaRebel y luego incluir -javaagent:/path/to/javarebel.jar en el arranque. (El tema de javaagent da al menos para otro post, pero básicamente es un “interceptor” del proceso de carga de clases, que permite monitorizar dicho proceso de carga y modificar el bytecode que se va a ejecutar… Esta funcionalidad es utilizada por algunas herramientas de profiling o frameworks de Programación Orientada a Aspectos)

En la propia página del producto podéis encontrar un flash que describe bastante bien nuestra situación inicial y también hay una demo real de como funciona esto…

Una de las cosas no tan buenas, además del problemita de ser de pago, es que no es posible depurar desde Netbeans (tienen identificado el bug pero de momento no han previsto cuando liberarán esa versión…) En cuanto a otros IDEs funciona correctamente para Eclipse y para IDEA IntelliJ.

Control de errores y argumentos variables

Wednesday, November 12th, 2008

Una de las cosas más importantes y obvias cuando escribimos un programa es preparar un buen control de errores. Esto que al principio parece algo fácil, sencillo y encapsulable, al final terminamos haciéndolo siempre de una manera diferente, ya que poco a poco se va complicando porque:
- controlamos la excepción y devolvemos un código de error, o si simplemente la propagamos
- qué herramienta/librería utilizamos para generar la información de log
- qué nivel de log vamos a mantener
- cómo vamos a informar del error
- …

Pero siempre hay algo que solemos olvidar, y es que, tan importante como la detección del error, es el registro del contexto en el que se estaba ejecutando el programa cuando falló, es decir, con qué datos estaba operando.
Este conjunto de datos, está claro que es variable en cada caso, con lo que pasárselo a un método genérico que registre el error suele ser algo lioso, a no ser que empleemos un método que acepte un número variable de argumentos no determinado inicialmente. Esta es una característica que antiguamente el C era uno de los pocos lenguajes que la soportaba, pero que es común en los lenguajes modernos (.NET, Java…), así en Java podríamos tener algo por el estilo:


public String generarCadenaParaLog(Object...args)
{
    StringBuilder logString = new StringBuilder();
    for(Object argTemp: args)
    {
        logString.append(argTemp);
    }
    return logString.toString();
}

Para llamarlo por ejemplo del siguiente modo:
...

    catch(Exception e)
    {

...

    // Recoger info error no esperado
    String errorNoEsperado =
      ErrorManager.generarCadenaParaLog(
                        "Error no esperado:",
                        "\nidCampaña", idCampaña,
                        "\nidUsuario:", idUsuario,
                        "\nimporte:", importeTransaccion);
    log(errorNoEsperado);
...

}

...

Servicios de windows e impresión de documentos

Friday, November 7th, 2008

  En un reciente proyecto me he encontrado con una situación no demasiado común: necesitábamos imprimir los documentos de Word desde un servicio sin interfaz de usuario. A los ya consabidos problemas de trabajar con documentos de Office en servidor (pero eso ya es otra historia….) se le añadía la dificultad de las pruebas en los entornos intermedios (en nuestro caso: desarrollo, integración y pre-producción), una vez verificado el resultado de la impresión.

  Primeramente intenté configurar uno de los múltiples drivers de impresión existentes en el mercado que acaban generando un documento en formato PDF y/o XPS. El problema era que todos ellos requerían de la interacción del usuario para seleccionar la ubicación del fichero a generar.

  La opción de implementar un mecanismo, que mediante configuración habilitara/deshabilitara la impresión de los documentos, la descarté porque podía acabar ocultando problemas en los entornos.

  La solución implementada consiste en la definición de una IMPRESORA NULA. Esto consiste en definir un nueva impresora local, asignándole un puerto nuevo local con valor “NUL:” En el siguiente paso de seleccionar el modelo podemos elegir cualquiera, puesto que los datos imprimidos se DESCARTAN DIRECTAMENTE. Para finalizar basta con asignarle un nombre significativo “Void Printer”, o “Impresora Pozo Negro” y configurarla en nuestro servicio en el modo adecuado

  De este modo habremos conseguido, sin alterar en lo más mínimo el comportamiento de la aplicación, trabajar con la aplicación evitando talar árboles de manera innecesaria.

  Os dejo unos pantallazos de la configuración de la impresora en mi máqiuna (Windows Vista). Por cierto, esto está probado en Windows Vista y Windows 2003 Server.

Problemas Team Foundation Build y ClickOnce

Friday, October 31st, 2008

En el proyecto actual nos hemos encontrado con la problemática de realizar construcciones automáticas de TFS con un proyecto de tipo “Office AddIn”. Este tipo de proyectos utilizan ClickOnce para el despliegue, lo cual implica firmar el manifest. Aunque esto es algo que podemos obviar cuando estamos trabajando en nuestra máquina, puesto que Visual Studio nos genera de manera automática un certificado con funcionalidad “Code Signing”, provoca errores de construcción en el servidor de integración

  • C:\WINDOWS\Microsoft.NET\Framework\v3.5\Microsoft.Common.targets(1805,7): error MSB3323: Unable to find manifest signing certificate in the certificate store.

Para resolver esto, basta con seguir estos pasos:

  1. Copiar el certificado utilizado para la firma, ya sea el generado por VS o uno de nuestra propia cosecha, a una carpeta del servidor de compilación
  2. Iniciar sesión con el usuario que ejecuta el servicio TFS Build
  3. Iniciar la consola de administración de certificados: Run => certmgr.msc
  4. Importar el certificado a la carpeta de certificados personales. En este momento se solicitará el password que le hayamos asignado.

A partir de este momento el certificado es accesible para el servicio de build y habremos solucionado el error anterior.

Salu2 a tod@s,

Depurando servicios WCF

Wednesday, July 30th, 2008

Aunque a estas alturas de la vida parezca mentira, depurar un servicio de WCF “selft-hosted” en Visual Studio 2008 da muchos dolores de cabeza. Para empezar, cuando estás depurando la aplicación aparece un maravilloso dialogo que te avisa que no vas a poder depurar el código del servicio (aun cuando no fueras a hacerlo!). Si, ignorando la advertencia, intentas hacer un “step into”, descubriras que el entorno no te permite meterte dentro y pasa a la siguiente instrucción.

Para conseguir hacerlo funcionar hay que realizar dos sencillos pasos (una vez que los conoces, claro):
1. Habilitar la depuración de servicios WCF en la máquina. Por defecto, el framework no permite hacer depuración remota de los servicios WCF. Esto es una característica que aumenta la seguridad y el rendimiento de estos. Lo malo es que somos desarrolladores y en nuestras máquinas queremos hacer de todo. La solución es bien sencilla:
a. Abrir el fichero “machine.config”. Su ubicación es: %windir%\Microsoft.NET\Framework\v2.0.50727\CONFIG\machine.config. Cuidado con lo que tocamos, esto es parte del core del framework. Si hacemos lago mal podemos dejarlo KO.
b. Buscar el nodo: configuration/system.servicemodel/commonBehaviours
c. Comentamos los dos nodos contenidos tanto en “endpointBehaviors” como en “serviceBehaviors”. Recordatorio: es un XML, los comentarios son del tipo

2. Editar la configuración de la solución de VS para que arranque múltiples proyectos al depurar:
a. Abrimos las propiedades de la solución y accedemos a “Common Properties/Starup Project”
b. Seleccionamos “Multiple Startup Projects”
c. Marcamos como “Start” todos los proyectos de WCF que queramos depurar. Nota: Para evitar que nos aparezca el cliente de pruebas (sobre todo si no vamos a probar el servicio por separado), basta con eliminar los argumentos de la línea de comandos del proyecto en cuestión.

Bueno, ha sido largo y seguramente bastante tedioso, pero confío en que os ayude y os haga más llevadero vuestros desarollos.

Salu2 y hasta la próxima,
C#

He leído: Foundations Of Programming Building Better Software

Monday, July 7th, 2008

Y os lo recomiendo, es un ebook gratuito, muy profesional, donde en 78 paginas muy amenas se tratan por encima muchas de las técnicas de desarrollo modernas:

Agile Development, Domain Driven Design, Persistance, Dependency Injection, Unit Testing, ORM Mappers así como fundamentos de programación como Memoria, Excepciones y el Patrón Proxy componen los temas principales del libro.

El link es http://codebetter.com/files/folders/codebetter_downloads/entry179694.aspx

Programación Orientada al Aspecto (AOP)

Thursday, March 27th, 2008

La Programación Orientada a Aspectos (POA u AOP) es un paradigma de programación relativamente reciente cuya intención es permitir una adecuada modularización de las aplicaciones y posibilitar una mejor separación de conceptos. Gracias a la POA se pueden encapsular los diferentes conceptos que componen una aplicación en entidades bien definidas, eliminando las dependencias entre cada uno de los módulos.

La mejor forma de entender en qué consiste y que proporciona es viendo un pequeño ejemplo utilizando de paso el framework Spring.

Iremos paso a paso para construir una aplicación con Spring AOP y al final del documento tenéis el código fuente del mismo y un PDF con todo el documento de Spring AOP

(more…)

A pie de código: sobrecarga del operador equals

Monday, March 10th, 2008

Plataforma: Todas.

¿Cuando sobrecargarlo?

Todas las plataformas tienen un operador de igualdad. Las plataformas basadas en runtime (JAVA y .NET) implementan en el objeto base de su jerarquía de clases un método “equals”. El lenguaje c++ implementa natívamente un operador sobrecargable ==.

En el caso de java la implementación por defecto realiza una comprobación de identidad. Esto es, que si en java escribimos

Object a = new Object();
Object b = new Object();

boolean out = a == b;
El resultado será siempre falso, y solo será verdadero si dos referencias apuntan al mismo objeto en memoria:

Object a = new Object();
Object b = a;

boolean out = a == b;

En el caso de .NET la implementación por defecto de Equals para tipos referencia se comporta de manera similar a la de java. En el caso de tipos valor lo que se hace es una comparación bit a bit del objeto completo, y solo será verdadera si todos los bits de los objetos comparados coinciden.

Dicho esto: ¿Cuando nos interesa sobrecargar equals?.

  1. Cuando el tipo que estamos implementando tiene semántica de valor. Es decir, cuando queremos que dos objetos sean iguales si su valor es igual.
  2. Cuando implementamos para un tipo un interfaz de comparación, tipo IComparer, para hacer coherente la igualdad del comparador y del método equals se implementa este último empleando el primero en su implementación.

  3. En el caso de tipos valor en .NET, es recomendable por rendimiento sobrecargar Equals siempre (y así se evita una comparación bit a bit para sustituirla por una comparación de campos).

¿Como sobrecargarlo?

Os pongo aquí debajo código de ejemplo. Está escrito en .NET, pero la lógica a seguir en java sería similar.

class MyType : ParentType
{

private Int32 a;
private Int32 b;

[....]

public override Boolean Equals(Object obj)
{

if (obj == null)
return false;

if (this.GetType() != obj.GetType())
return false;

MyType tp = (MyType) obj;

if ((this.a != tp.a) || (this.b != tp.b))
return false;

// En caso de descender de Object o de
// ValueType (en .NET).
// return true;

return base.Equals(obj);

}

[...]

}

¿Que más tengo que tener en cuenta?

  1. Equals nunca tiene que retornar una excepción, por lo que no se debe incluir código que pueda generar excepciones.
  2. Siempre que se implementa Equals, hay que implementar las funciones de generación de hash. No quiero entrar en mucho detalle, pero escribo un ejemplo de como implementar getHashCode(). Nótese que el hash se genera con los mismos campos que intervienen en equals.

    class MyType : ParentType
    {

    private Int32 a;
    private Int32 b;

    [...]

    public override Int32 GetHashCode()
    {
    return a.GetHashCode() ^ b.GetHashCode() ^ base.GetHashCode();
    }

    [...]
    }

  3. Es muy recomendable implementar una función Equals sobrecargada para el tipo concreto. Es decir.

    public virtual boolean Equals(MyType arg)
    {
    [...]
    }

  4. Si se implementa un comparador (Como ICompare en .NET), implementar Equals en función del comparador.

    public override Boolean Equals(Object obj)
    {
    if (obj == null)
    return false;

    if (this.GetType() != obj.GetType())
    return false;

    return this.CompareTo(obj) == 0;
    }

  5. Recordar que existe el operador ==, que tiene que ser implementado con Equal si se desea. Es recomendable darle la misma lógica que a Equals.