miércoles, septiembre 02, 2009

Validando contra LDAP - Active Directory

Bueno, sobre esto existe mucha documentación por el mundo y la verdad que no soy un experto, en mi caso he tenido que hacer una pequeña modificación a una aplicación de uso interno para que valide el usuario que quiere acceder usando el mismo usuario y contraseña que se usa para acceder al dominio. La historia se resume en que el servidor Tomcat esta en Windows dentro de un dominio con Active Directory, donde se gestionan los usuarios y grupos.

Validar directamente sobre Active Directory al parecer requiere de ciertas llamadas al sistema operativo, una DLL vamos (o al menos eso es lo que yo he entendido recopilando información desde google). Yo encontré una librería que usa un plug-in de Hudson para validar sobre active directory, se llama "active directory" (como no) y la ha desarrollado un tal Kohsuke Kawaguchi (su blog y la entrada donde explica la integración de hudson y active directory).

La librería esta muy bien y a mi me funcionó todo a la primera, pero tenia el inconveniente de la dependencia de una DLL y que el servidor estuviese sobre windows, como estamos intentando migrar algunos sistemas a Linux no quise arriesgarme, así que en lugar de hacerlo así usé LDAP sobre el directorio, que aquí esta configurado para que funcione (no me pregunten como se configura que eso es cosa de sistemas).

Al final el código queda tan simple  que he pensado que es interesante comentarlo.
DirContext ctx = null;
 Hashtable env = new Hashtable();
 env.put(Context.INITIAL_CONTEXT_FACTORY,
    "com.sun.jndi.ldap.LdapCtxFactory");
 env.put(Context.PROVIDER_URL, "ldap://domain.corp");
 env.put(Context.SECURITY_PRINCIPAL, username + "@domain.corp");
 env.put(Context.SECURITY_AUTHENTICATION, "simple");
 env.put(Context.SECURITY_CREDENTIALS, password);
 try {
   ctx = new InitialDirContext(env);
   // connected. Login success 

    return true;
 } catch (Exception ex){ 

  LOGGER.log(Level.SEVERE, "Authentication exception : " + ex.getMessage());
} finally {
  if (ctx != null) {
    try { ctx.close(); }
    catch (NamingException e) {
       LOGGER.info("Naming exception : " + e.toString());
}}}
return false;

Y ya está, por supuesto además se puede verificar a que grupo pertenece el usuario y en función de eso, dar diferentes permisos. Espero que a alguien le sirva, hay mucha información sobre esto por ahí.

martes, agosto 25, 2009

Decompilando Java

Afortunadamente son pocas las ocasiones en los que un código, más o menos esencial, se pierden las fuentes. Hoy en día siempre se sigue el mismo protocolo de usar un SVN u otro sistema de control de versiones para ir almacenando el código fuente. Sin embargo, por pura ley de Murphy, siempre puede darse uno de esos casos improbables. En mi caso se está usando una versión de JAR que no tiene el código en el SVN.

Cuando esto ocurre la solución más rápida pasa por los decompiladores de código java. Usando estas herramientas es posible extraer desde los ficheros binarios ".class" una versión bastante similar al código original.

Yo he encontrado algunas soluciones interesantes, las enumero aquí y así las hago públicas:
  • DJ Decompile. Es una aplicación comercial, bastante interesante. Tiene una versión de evaluación de algunos días/usos y para una emergencia puede servir.
  • JAD es una librería para decompilado de java (el sitio oficial no esta disponible. He encontrado un mirror). Yo encontré un programa llamado "FrontEnd plus"como herramienta GUI que usa esta librería internamente, aunque he encontrado más aquí : http://blogninja.com/doc/jad/jad.html#gui
  • Y el que mas me gusta, el plug-in para eclipse (que también es aplicación para escritorio) JD-Eclipse. Más información : http://java.decompiler.free.fr/
Finalmente he optado por esta última opción, sólo requiere tener las clases dentro del classpath de un proyecto eclipse y con un simple click puedes ver el código fuente, puede servirme para alguna que otra librería que no sé como funciona.


jueves, agosto 06, 2009

FileSets en Ant

Bueno, como dije en mi anterior post, voy a intentar resumir las cosas nuevas con las que he tenido que trabajar estos meses. Una de ellas son las tareas "ant" personalizadas. Últimamente he tenido que modificar y crear algunos scripts ant para muchas operaciones diferentes y en mas de una ocasión me he encontrado con situaciones que el script necesita hacer operaciones "poco comunes". En mi caso, consistía en localizar el último fichero modificado en una carpeta.

No quería copiarlo, moverlo ni nada parecido, solo saber cual era. Así que tuve que hacer una tarea para ello. La funcionalidad que busco es, dada una carpeta, localizar el ultimo fichero modificado usando patrones de búsqueda por nombre (include - exclude).

Al final el código del script viene a quedar como esto :

<lastFile property="my.property">
   <fileset dir="C:/FOLDER">
     <include name="**/*.exe" />
     <exclude name="*Setup*" />
   </fileset>
</lastFile>

Aquí vemos como la tarea "lastFile" debe de buscar todos los ejecutables en la carpeta "C:\FOLDER" excepto aquellos que contengan "Setup" en su nombre y guardar en la propiedad "my.property" el nombre de este. Ahora lo que toca es ponerse manos a la obra y ver el código Java. Para ello empezamos creando una clase que será nuestra tarea:

import org.apache.tools.ant.Task;
import org.apache.tools.ant.types.FileSet;

public class LastFile
    extends Task
{
  private String property;
  private Vector <Fileset>
 filesets = new Vector<Fileset>();

  public void addFileset(FileSet fileset)  {
    filesets.add(fileset);
  }

  public void setProperty(String property) {
    this.property = property;
  }


  public String getProperty() {
    return property;
  }

  protected void validate() {
         if (property == null)
      throw new BuildException("property not set", getLocation());
    if (filesets.size() < 1)
                throw new BuildException("You must specify a fileset", getLocation());
     }
          @Override
          public void execute()
              throws BuildException
          {
              // Mi código va aquí
          }
} // End Class

Como se ve, ahora mismo la clave está en la propiedad "filesets", en la que se añaden elementos del tipo "FileSet". Este elemento nos permite saber los ficheros existentes en la carpeta indicada. Ahora la clave está en como usarlo. Así que nos vamos al corazón de la tarea, al método "execute". Primero veamos como lo hice yo.

validate(); // 1
long newest = 0;
File last = null;
for (FileSet fs : filesets)
{
    if (fs.getProject() == null)  {
        fs = (FileSet) fs.clone();
        fs.setProject(getProject());
    }
    File dir = fs.getDir();
    log("searching last file in " + dir);
    // Obtenemos una instancia del scanner del directorio
    DirectoryScanner ds = fs.getDirectoryScanner(getProject());
    // Una lista de los ficheros incluidos
    String[] includedFiles = ds.getIncludedFiles();
    for (String filename : includedFiles) {
        log("--> " + filename);
        File currentFile = new File(dir, filename);
        if (!currentFile.isDirectory())
        {
          // Para cada fichero, obtenemos la fecha y nos
          // quedamos con el último
          long lastModified = currentFile.lastModified();
          if (lastModified > newest)
          {
            newest = lastModified;
            last = currentFile;
          }
        }
    }
    if (last == null)
    {
        log("No file was found", Project.MSG_WARN);
    } else  {
        String value;
        value = last.getAbsolutePath();
        log("Find the last file " + last.getName(), Project.MSG_INFO);
        log("Setting propery '" + getProperty() + "' to value '" + value + "'");
        getProject().setProperty(getProperty(), value);
    }
}

Lo importante con lo que hay que quedarse es que una vez tengamos el FileSet, podemos obtener todos los ficheros que estan incluido (incluso los excluidos) y trabajar con ellos. Cualquier duda, en los comentarios. El código esta disponible dentro de mi SVN en http://code.google.com/p/guevonaso-codes/

miércoles, agosto 05, 2009

El tiempo pasa

Bueno, han pasado.. ¿cuanto? casi tres meses desde mi último post. Quiero pedir disculpas por el retraso pero han sido unos meses de mucho (realmente mucho) estrés, tanto en el trabajo como en casa, y no he tenido tiempo de poder actualizar nada, espero que a partir de ahora tenga una jornada mas "normal" y me de tiempo a ponerme al día en actualizar el blog con todas las cosas que he aprendido estos meses, que no han sido pocas.

En breve una actualización hablando otra vez de Java y sus cosillas.

martes, mayo 12, 2009

Blog personal en civinova.org

El otro día comenzó un nuevo proyecto que mi amigo Ibán está llevando con mucha ilusión. Se llama http://civinova.org y http://civinova.com. Como indica en la web :

CiviNova Es una ciudad virtual dedicada a la cultura donde los usuarios (ciudadanos) cuentan con todo lo necesario para dar a conocer su obra. Para los creadores hay gremios de escritores, pintores, músicos... Y para todos, grupos de literatura, arte, música, cine... ¿Te lo vas a perder?

civi Nova es, además, una revista, una editorial y un hosting para alojamiento y creación de webs culturales.

Es decir, civinova es una nueva red social y una revista de cultura en la que cualquiera que se considere creador y/o artista puede empezar a dar a conocer su obra sin complicaciones y ver las creaciones de otros miembros de la "ciudad".

El proyecto está aún en una fase inicial en la que se han puesto en marcha las herramientas básicas necesarias, pero se espera que la cosa vaya creciendo. Animo a todo el mundo desde mi humilde blog a que os acerquéis a echar un vistazo y si os atrevéis, a crear vuestro perfil de ciudadano. Yo por mi parte he decidido que mi blog personal sea ahora el de civinova http://www.civinova.org/pg/blog/guevonaso . No sé que pasará con http://guevonaso.blogspot.com, supongo que seguirá existiendo, pero no lo sé. En cualquier caso, desde aquí deseo toda la suerte del mundo a Ibán en su proyecto

lunes, mayo 04, 2009

Actualizando hola mundo struts 2

Este es un post corto. He reorganizado un poco el código del proyecto de hola mundo del post anterior. Estoy intentando hacer que el proyecto se pueda desplegar usando maven, ya comentaré mis experiencias. La verdad es que está siendo un poco más frustrante de lo que pensé en un momento. Un buen enlace para ver como hacerlo en castellano: Hola mundo con google App Engine y maven. Esta traducido y resumido de otro blog que además tiene en uno de sus comentarios una referencia a esto mismo y que además está creando un "archetype" para maven para crear proyecto de google. Muy didactico seguir la secuencia completa.

Por ahora me conformo con haber podido simplifiar el ejemplo anterior para poder ampliarlo poco a poco.

domingo, abril 26, 2009

Struts 2 en google-app-engine

Buenas, he tenido estas últimas semanas mucho (pero mucho) trabajo y no he podido añadir nada nuevo al blog por falta de tiempo. La noticia java durante este tiempo ha sido (a parte de la compra de Sun por parte de Oracle) el hecho de que google haya dado soporte Java en su engine además de python.

La noticia es genial para todos los que queríamos hacer una aplicación web pública sin costes y sin tener que depender de PHP. El servicio puede hacerse de pago, puesto que la version gratuita tiene una serie de limitaciones de ancho de banda y consumo de CPU, pero sin publicidad incluida.

Pero yo no quería hablar de las bondades del servicio de google, si no de como poder utilizar algún framework dentro de este. Casi a la vez que salió la noticia he encotrado varios sitios hablando del tema, enumero aqui :

Y mi aportación a este mundo es recoger esta informacion y explicar en cuatro pasos simples el hola mundo de Struts 2. No se hasta que punto funcionará todo, pero por probar que no quede.

Asumo que ya se ha configurado eclipse y habeis hecho el primer "Hola Mundo" usando el AppEngine SDK.

Una vez tenemos nuestra aplicación de pruebas funcionando, pasamos al siguiente paso, nos bajamos las librerias de struts. Las podemos encontrar en la página oficial o usando maven. Yo me las he descargado a mano, la versión que contiene solo los jar necesarios y la que contiene las applicaciones de ejemplo (llamada struts-2.1.6.apps.zip ).

Mi intención es simplemente ejecutar el "HelloWorld", por lo que descomprimo el helloworld.war.

El siguiente paso es tan simple como copiar las librerias en la carpeta "lib" y modificar el web.xml añadiendo el filtro de Struts, los JSPs de ejemplo y las clases de ejemplo y los XML que la aplicacion a mi proyecto creado con eclipse.

La estructura del proyecto eclipse queda algo tal y como se muestra en la imagen a continuacion.

Si tal y como tenemos el proyecto ahora mismo, la aplicación falla. Nos provocará un error provocado por las restricciones que el engine de google ha introducido en su máquina virtual y que hacen incompatible el funcionamiento por defecto del OGNL. La solución la he encontrado en uno de los enlaces anteriores que me ha llevado a esta entrada de un foro. En ella se describe que la solución es muy simple, crear un listener que nos permita configurar la gestión de seguridad de OGNL.

El codigo del listener sería:

public class InitListener implements
ServletContextListener
{
public InitListener()
{ }

public void
contextInitialized(ServletContextEvent sce)
{
OgnlRuntime.setSecurityManager(null);
}
// El resto de metodos necesarios se dejan vacios.

Incluimos el listener en el web.xml :

<web-app>
<!-— El filtro de struts 2 -->
<filter>
    <filter-name>struts2</filter-name>
    <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>struts2</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>
<listener>
    <listener-class>es.guevonaso.InitListener</listener-class>
</listener>
<servlet>
    <servlet-name>guevonaso</servlet-name>
    <servlet-class>es.guevonaso.guevonasoServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>guevonaso</servlet-name>
    <url-pattern>/guevonaso</url-pattern>
</servlet-mapping>
<welcome-file-list>
    <welcome-file>index.html</welcome-file>
</welcome-file-list>
</web-app>
Una vez funcionando nos mostrará un mensaje de error de que las sesiones no están configuradas. Para eso solo debemos de modificar el fichero appengine-web.xml y añadir el parámetro "sessions-enabled":
<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
  <application>guevonaso</application>
  <version>1</version>
  <!-- Configure java.util.logging -->
  <system-properties>
      <property name="java.util.logging.config.file" value="WEB-INF/logging.properties"/>
  </system-properties>
  <sessions-enabled>true</sessions-enabled>
</appengine-web-app>

Y listo, esto nos permite tener un hola mundo empleando struts 2. Ahora es cosa de verificar hasta que punto podemos usar esta librería. Mientras tanto, el codigo de este ejemplo lo podéis encontrar donde siempre en http://code.google.com/p/guevonaso-codes/, con la salvedad de que no he subido los ficheros binarios "JAR", de la carpeta "lib". Y la aplicación de pruebas esta en : http://guevonaso.appspot.com/example

  • El ejemplo de un formulario
  • Hola mundo