<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Fotografía Juan Díez-Yanguas &#187; Informática</title>
	<atom:link href="http://blog.jdiezfoto.es/category/informatica/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.jdiezfoto.es</link>
	<description>Blog</description>
	<lastBuildDate>Tue, 21 Feb 2012 18:00:46 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
<xhtml:meta xmlns:xhtml="http://www.w3.org/1999/xhtml" name="robots" content="noindex" />
		<item>
		<title>Spotbros: Un ejemplo de como hacer las cosas bien</title>
		<link>http://blog.jdiezfoto.es/informatica/spotbros-un-ejemplo-de-como-hacer-las-cosas-bien/</link>
		<comments>http://blog.jdiezfoto.es/informatica/spotbros-un-ejemplo-de-como-hacer-las-cosas-bien/#comments</comments>
		<pubDate>Tue, 21 Feb 2012 10:38:48 +0000</pubDate>
		<dc:creator>Juan</dc:creator>
				<category><![CDATA[Informática]]></category>
		<category><![CDATA[Android]]></category>

		<guid isPermaLink="false">http://blog.jdiezfoto.es/?p=2132</guid>
		<description><![CDATA[<p>Esta semana pasada navegando por una de mis webs sobre Android me encontré con una nueva aplicación al estilo Whatsapp, pero bien distinta; el artículo me convenció y decidí probarla y la sorpresa ha sido tan agradable que aquí estoy escribiendo un artículo sobre ella. La aplicación se llama Spotbros, es nueva, acaba de salir <a href='http://blog.jdiezfoto.es/informatica/spotbros-un-ejemplo-de-como-hacer-las-cosas-bien/' class='excerpt-more'>[...]</a></p><p><p>© 2009-2011 Juan Díez-Yanguas Barber </p></p>]]></description>
			<content:encoded><![CDATA[<p style="text-align: center;"><a href="http://www.spotbros.com/es"><img class="aligncenter  wp-image-2159" title="SpotbrosLogo" src="http://blog.jdiezfoto.es/wp-content/uploads/2012/02/SpotbrosLogo.png" alt="" width="635" height="311" /></a></p>
<p>Esta semana pasada navegando por una de mis webs sobre Android me encontré con una nueva aplicación al estilo Whatsapp, <a href="http://www.elandroidelibre.com/2012/02/la-alternativa-a-whatsapp-mas-segura-estable-y-versatil-se-llama-spotbros.html" target="_blank">pero bien distinta</a>; el artículo me convenció y decidí probarla y la sorpresa ha sido tan agradable que aquí estoy escribiendo un artículo sobre ella.</p>
<p>La aplicación se llama <a href="http://www.spotbros.com/es" target="_blank">Spotbros</a>, es nueva, acaba de salir en enero y está en versión beta; se trata de una aplicación de <strong>mensajería instantánea vía internet por push</strong> al estilo de Whatsapp, pero seguro, bien hecho y encima con unas ideas añadidas bastante interesantes e innovadoras.</p>
<p><span id="more-2132"></span>Convendría comentar que no estaría escribiendo esto sino me hubiera llamado tan gratamente la atención en muchos aspectos, comencemos describiendo la aplicación.</p>
<p>Como he dicho no es algo nuevo, ya existe, lo tenemos, pero&#8230; ¿lo que tenemos es lo mejor? Yo diría que no, entre funcionamiento, fiabilidad, calidad y seguridad hay diferencias; muchas veces parece que importa más el que primero saca la idea que el que saca la idea con mejor calidad.</p>
<p>Pues si es algo que ya tenemos habrá que ver las diferencias ¿no?. Pues vamos a ello; en primer lugar es seguro, todas las comunicaciones son encriptadas usando <strong><a href="http://es.wikipedia.org/wiki/Advanced_Encryption_Standard" target="_blank">AES</a> de 256 bits</strong>, uno de los algoritmos de encriptación más seguros que hay. Mayor privacidad, todo rastro de nuestras conversaciones es <strong>borrado de sus servidores a los 30 días</strong> y nadie nos puede hablar sino le conocemos, es necesario que <strong>los dos extremos de la comunicación tengan al otro usuario en la agenda</strong>. Mayor <strong>eficiencia y fiabilidad</strong>, a pesar de estar en beta he notado una aplicación muy fluida y sin ningún cuelgue, e incluso he notado menor <strong>consumo de batería</strong> que con otros servicios.</p>
<p><img class="alignleft size-full wp-image-2146" title="SpotbrosSpots" src="http://blog.jdiezfoto.es/wp-content/uploads/2012/02/SpotbrosSpots.png" alt="" width="242" height="212" />Y además, no solo han mejorado lo existente por mucho sino que han añadido nuevas funcionabilidades bajo mi punto de vista interesantes e innovadoras.</p>
<p>Veamos que cosas son las que han introducido como nuevas.</p>
<p>En primer lugar, se permiten grupos, pero&#8230; ¿solo grupos? Pues no, tiene la opción de los grupos tradicional y una nueva forma de grupo bajo el nombre de <strong><em>spots</em></strong>. Grupos asignados a un lugar, se pueden crear y unir a ellos, y se muestran los que hay a tu alrededor, una forma de añadir a la aplicación funciones sociales que pueden ser muy útiles.</p>
<p><img class="size-full wp-image-2144 alignright" title="SpotbrosShout" src="http://blog.jdiezfoto.es/wp-content/uploads/2012/02/SpotbrosShout.png" alt="" width="242" height="212" /></p>
<p>Y finalmente, un añadido más, ellos lo llaman <strong><em>shouts</em></strong>, pero se podría llamar un mensaje de <em>broadcast</em>, o un mensaje a todo el mundo; esta función manda un mensaje a todos en un radio de 1.5km. Sin duda algo muy interesante para poder mandar comunicaciones a tu alrededor, y podría ser de mucha ayuda ante una emergencia por ejemplo. Algunos podrán pensar que esto puede ser un medio de spam, pero lo cierto es que los chicos de <a href="http://www.spotbros.com/es" target="_blank"><strong>Spotbros</strong></a> lo saben y tienen en mente numerosas ideas interesantes para evitar esto.</p>
<p>También han mejorado lo ya existente en el envío de mensajes, en concreto en lo que se refiere a los mensajes multimedia. Permiten enviar varias imágenes en un mismo mensaje; y lo que ahora son fotos en próximas versiones serán fotos, vídeos, audio y mapas todo ello en un mismo mensaje. No cabe duda de que lo que tenemos ante nuestros ojos es una obra de la innovación que en este caso va de la mano con la calidad.</p>
<p><img class="alignleft size-full wp-image-2153" title="imagesSpotbros" src="http://blog.jdiezfoto.es/wp-content/uploads/2012/02/imagesSpotbros.png" alt="" width="242" height="230" /></p>
<p>Bueno, y por terminar comentar algo acerca del soporte, no he visto soporte igual en mucho tiempo, respuesta en poco tiempo, una respuesta personalizada, simpática, interesándose por un problema, muy educados, y además eficientes.</p>
<p>La aplicación de momento está disponible para <strong>android y para iphone</strong> está en desarrollo; de manera que también es multiplataforma.</p>
<p>Bueno, finalmente hacer notar que esto no es un artículo patrocinado ni nada que se le parezca, simplemente he probado la aplicación, me ha dado una muy grata sorpresa y creo que tiene mucho potencial detrás, y de ahí que este escribiendo este artículo.</p>
<p>Lo malo: todavía, como es normal no lo tiene mucha gente, pero creo sinceramente que con este potencial puede llegar muy lejos, solo necesitan nuestra ayuda para crecer poco a poco.</p>
<p>NOTA: Las imágenes del artículo son propiedad de <a href="http://www.spotbros.com/es/" target="_blank">Spotbros Technologies S.L.</a></p>
<h4  class="related_post_title">Artículos más comentados</h4><ul class="related_post"><li><a href="http://blog.jdiezfoto.es/informatica/ejemplo-javaee-una-tienda-online/" title="Ejemplo Java EE: Una tienda Online">Ejemplo Java EE: Una tienda Online</a></li><li><a href="http://blog.jdiezfoto.es/santander/fuegos-artificiales-semana-grande-santander-2010/" title="Fuegos artificiales Semana Grande Santander 2010">Fuegos artificiales Semana Grande Santander 2010</a></li><li><a href="http://blog.jdiezfoto.es/santander/los-reflejos-del-sol/" title="Los reflejos del sol">Los reflejos del sol</a></li><li><a href="http://blog.jdiezfoto.es/fotografia/mezquita-de-cordoba/" title="Mezquita de Córdoba">Mezquita de Córdoba</a></li><li><a href="http://blog.jdiezfoto.es/santander/llovera-o-no-llovera/" title="Lloverá o no lloverá">Lloverá o no lloverá</a></li><li><a href="http://blog.jdiezfoto.es/santander/playa-de-arnia-como-en-el-caribe/" title="Playa de Arnia: Como en el Caribe">Playa de Arnia: Como en el Caribe</a></li><li><a href="http://blog.jdiezfoto.es/general/adaptarse-o-morir/" title="Los tiempos cambian">Los tiempos cambian</a></li></ul><p><p>© 2009-2011 Juan Díez-Yanguas Barber </p></p>]]></content:encoded>
			<wfw:commentRss>http://blog.jdiezfoto.es/informatica/spotbros-un-ejemplo-de-como-hacer-las-cosas-bien/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>JRebel: Stop Redeploying</title>
		<link>http://blog.jdiezfoto.es/informatica/jrebel-stop-redeploying/</link>
		<comments>http://blog.jdiezfoto.es/informatica/jrebel-stop-redeploying/#comments</comments>
		<pubDate>Sat, 18 Feb 2012 12:18:11 +0000</pubDate>
		<dc:creator>Juan</dc:creator>
				<category><![CDATA[Informática]]></category>
		<category><![CDATA[Java]]></category>

		<guid isPermaLink="false">http://blog.jdiezfoto.es/?p=2104</guid>
		<description><![CDATA[<p>Esta semana que se va ha sido el SpringI/O en la Universidad San Pablo CEU, mi universidad. Mi función en este evento ha sido básicamente ayudar en lo que he podido, lo que  no quita que haya podido ver cosas realmente interesantes, y entre ellas de la que hoy os voy a hablar: JRebel &#38; <a href='http://blog.jdiezfoto.es/informatica/jrebel-stop-redeploying/' class='excerpt-more'>[...]</a></p><p><p>© 2009-2011 Juan Díez-Yanguas Barber </p></p>]]></description>
			<content:encoded><![CDATA[<p style="text-align: center;"><a href="http://zeroturnaround.com/"><img class="aligncenter size-full wp-image-2105" title="JRevelLiveRebel" src="http://blog.jdiezfoto.es/wp-content/uploads/2012/02/JRevelLiveRebel.png" alt="" width="510" height="91" /></a></p>
<p style="text-align: left;">Esta semana que se va ha sido el <a href="http://springio.net/" target="_blank">SpringI/O</a> en la Universidad San Pablo CEU, mi universidad. Mi función en este evento ha sido básicamente ayudar en lo que he podido, lo que  no quita que haya podido ver cosas realmente interesantes, y entre ellas de la que hoy os voy a hablar: <strong><a href="http://zeroturnaround.com/jrebel/" target="_blank">JRebel</a> &amp; <a href="http://zeroturnaround.com/liverebel/" target="_blank">LiveRebel</a></strong>.</p>
<p><span id="more-2104"></span><br />
Ambos productos de la empresa <strong><a href="http://zeroturnaround.com/" target="_blank">ZeroTurnaroud</a></strong> proveniente de Estonia. Tienen como idea principal facilitar al desarrollador de aplicaciones web la tediosa tarea de guardar, para el servidor y redesplegar. Ahora estas tareas se harán de manera totalmente transparente a nosotros. Veamos la idea principal de ambos productos.</p>
<p style="text-align: left;"><span style="font-size: x-large;"><strong>JRebel: Para desarrolladores</strong></span></p>
<p style="text-align: left;">El la idea final del producto es ayudar a los desarrolladores Java EE y ahorrarles tiempo en tareas tediosas que se dan en este entorno. Esto es, cada vez que hacemos cambios en una aplicación hay que <strong>guardar los cambios</strong>, parar la aplicación y <strong>redesplegar la aplicación</strong> de nuevo en el servidor de aplicaciones.</p>
<p style="text-align: center;"><img class="aligncenter  wp-image-2110" title="JRebel" src="http://blog.jdiezfoto.es/wp-content/uploads/2012/02/JRebel-1024x719.jpg" alt="" width="556" height="390" /></p>
<p style="text-align: left;">Aunque este problema este medianamente solucionado por lo menos en NetBeans que sí permite realizar estas acciones en caliente la solución no funciona para todos los tipos de cambios.</p>
<p style="text-align: left;">Y aquí es donde entra <strong>JRebel</strong>, el cual realiza estas tareas para tí de manera <strong>automática y transparente</strong>, y no solo eso sino que admite todo tipo de cambios (los podemos ver en su <a href="http://zeroturnaround.com/jrebel/features/" target="_blank">web</a>). Y no solo eso, sino que soporta los  <strong>principales IDEs (NetBeans, Eclipse&#8230; ) y servidores de aplicaciones (GlassFish, Tomcat, SpringSource, JBoss &#8230;)</strong>.</p>
<p style="text-align: left;">Hoy nos han hecho una demo a varios compañeros y a mí y he de decir que funciona realmente bien. Me parece una herramienta realmente útil para desarrolladores.</p>
<p style="text-align: left;">El inconveniente: Es de pago, aunque hay <a href="http://sales.zeroturnaround.com/" target="_blank">varias versiones</a> dependiendo de las características con precios diferentes; y también una versión gratuita para usos no comerciales. Y algo realmente interesante es la posibilidad de probar <a href="http://zeroturnaround.com/jrebel/current/" target="_blank"><strong>gratuitamente la versión completa durante 30 días</strong></a>.</p>
<p style="text-align: left;"><span style="font-size: x-large;"><strong>LiveRebel: En producción</strong></span></p>
<p style="text-align: left;">La idea de este producto es algo más complicada, orientada a las aplicaciones en producción y con un público más reducido.</p>
<p style="text-align: left;">Se trata de extender la idea de JRebel a un entorno de producción permitiendo principalmente actualización de las aplicaciones en caliente; la idea es retener las peticiones al servidor mientras la nueva versión de la aplicación es desplegada en el servidor y posteriormente pasar las peticiones al servidor como si nada hubiera ocurrido.</p>
<p style="text-align: center;"><img class="aligncenter  wp-image-2115" title="LiveRebel" src="http://blog.jdiezfoto.es/wp-content/uploads/2012/02/LiveRebel-1024x955.jpg" alt="" width="596" height="557" /></p>
<p style="text-align: left;">Tiene también otra <a href="http://www.youtube.com/watch?feature=player_embedded&amp;v=In08bPVLNz0" target="_blank">serie de funciones</a> como la comparación de versiones, integración contínua &#8230;, aunque sin duda alguna la más interesante de ellas me ha parecido la primera. No obstante, hoy se debatía entre los que estábamos viendo la demo la utilidad real de este proyecto, ya que, al fin y al cabo la mayoría de las veces no es un gran inconveniente parar el servidor por un corto periodo de tiempo para actualizar la aplicación web.</p>
<p style="text-align: left;">Esta herramienta como era de esperar tampoco es gratuita, y también consta de <a href="http://zeroturnaround.com/liverebel/pricing/" target="_blank">varias versiones</a> con varios precios dependiendo de las características. Tiene disponible una <strong><a href="http://zeroturnaround.com/liverebel/current/" target="_blank">evaluación de 90 días</a></strong>.</p>
<hr />
<p>En resumen, JRebel me parece una fantástica herramienta que puede ayudar a muchísimos desarrolladores y ahorrarles mucho tiempo en el desarrollo de aplicaciones web.</p>
<p>He de recalcar que este artículo no es ningún tipo de patrocinio, se ha escrito porque vi la demo y lo que me contaron y me ha parecido que debería darse a conocer en más idiomas.</p>
<p>NOTA: Las imágenes son propiedad de <a href="http://zeroturnaround.com/about-us/" target="_blank">ZeroTurnaround</a>.</p>
<h4  class="related_post_title">También te puede interesar:</h4><ul class="related_post"><li><a href="http://blog.jdiezfoto.es/informatica/vanadium-validacion-de-formularios-con-jquery/" title="Vanadium: Validación de formularios con JQuery">Vanadium: Validación de formularios con JQuery</a></li><li><a href="http://blog.jdiezfoto.es/informatica/tienda-online-java-ee-solucionada-validacion-ajax-en-formulario-de-registro/" title="Tienda Online Java EE: Solucionada validación ajax en formulario de registro">Tienda Online Java EE: Solucionada validación ajax en formulario de registro</a></li><li><a href="http://blog.jdiezfoto.es/informatica/java-ee-seguridad-en-aplicaciones-web-ii-evitando-inyeccion-sql-y-xss-con-esapi/" title="Java EE: Seguridad en aplicaciones web (II). Evitando Inyección SQL y XSS con ESAPI">Java EE: Seguridad en aplicaciones web (II). Evitando Inyección SQL y XSS con ESAPI</a></li><li><a href="http://blog.jdiezfoto.es/informatica/tutorial-ant-uso-con-librerias-externas-y-generadores-jflex-y-cup/" title="Tutorial ANT: Uso con librerías externas y generadores JFlex y CUP">Tutorial ANT: Uso con librerías externas y generadores JFlex y CUP</a></li><li><a href="http://blog.jdiezfoto.es/informatica/java-ee-seguridad-en-aplicaciones-web-i/" title="Java EE: Seguridad en aplicaciones web (I)">Java EE: Seguridad en aplicaciones web (I)</a></li><li><a href="http://blog.jdiezfoto.es/informatica/java-ee-6-subida-de-imagenes-al-servidor-servlet-3-0/" title="Java EE 6: Subida de imágenes al servidor (Servlet 3.0)">Java EE 6: Subida de imágenes al servidor (Servlet 3.0)</a></li><li><a href="http://blog.jdiezfoto.es/informatica/ejemplo-javaee-una-tienda-online/" title="Ejemplo Java EE: Una tienda Online">Ejemplo Java EE: Una tienda Online</a></li></ul><p><p>© 2009-2011 Juan Díez-Yanguas Barber </p></p>]]></content:encoded>
			<wfw:commentRss>http://blog.jdiezfoto.es/informatica/jrebel-stop-redeploying/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Vanadium: Validación de formularios con JQuery</title>
		<link>http://blog.jdiezfoto.es/informatica/vanadium-validacion-de-formularios-con-jquery/</link>
		<comments>http://blog.jdiezfoto.es/informatica/vanadium-validacion-de-formularios-con-jquery/#comments</comments>
		<pubDate>Wed, 01 Feb 2012 09:05:13 +0000</pubDate>
		<dc:creator>Juan</dc:creator>
				<category><![CDATA[Informática]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[JavaScript]]></category>

		<guid isPermaLink="false">http://blog.jdiezfoto.es/?p=1790</guid>
		<description><![CDATA[<p>Recientemente he anunciado en el blog por medio de una pequeña anotación que había sido subsanado uno de los problemas que tenía la tienda online en Java EE. La tienda había sido dotada de un mecanismo para validar en el registro si un email estaba ocupado o no, pero esta función no llegó a funcionar <a href='http://blog.jdiezfoto.es/informatica/vanadium-validacion-de-formularios-con-jquery/' class='excerpt-more'>[...]</a></p><p><p>© 2009-2011 Juan Díez-Yanguas Barber </p></p>]]></description>
			<content:encoded><![CDATA[<p style="text-align: center;"><a href="http://vanadiumjs.com/" target="_blank"><img class="aligncenter  wp-image-1796" title="vanadiumLogo" src="http://blog.jdiezfoto.es/wp-content/uploads/2012/01/vanadiumLogo.png" alt="" width="622" height="262" /></a></p>
<p>Recientemente he anunciado en el blog por medio de <a href="http://blog.jdiezfoto.es/informatica/tienda-online-java-ee-solucionada-validacion-ajax-en-formulario-de-registro/">una pequeña anotación</a> que había sido subsanado uno de los problemas que tenía la <a href="http://blog.jdiezfoto.es/informatica/ejemplo-javaee-una-tienda-online/">tienda online en Java EE</a>. La tienda había sido dotada de un mecanismo para validar en el registro si un email estaba ocupado o no, pero esta función no llegó a funcionar (aunque sí estaba implementada) por razones que hasta hace poco desconocía.</p>
<p>Dicho esto, creo que una vez solucionado este problema podría ser un buen momento para que os hablara en profundidad de las validaciones realizadas en los formularios de la tienda en el lado del cliente.</p>
<p><span id="more-1790"></span></p>
<p>Creo que sería una buena manera de empezar siendo sinceros y comentando que no soy ni un experto en JavaScript ni en <a href="http://jquery.com/" target="_blank">JQuery</a>, sin embargo si he aprendido a realizar la tarea que os voy a mostrar hoy a base de investigar bastante sobre el asunto concreto que esta vez nos atañe y de luchar para que aquello funcionara correctamente.</p>
<p>Cuando me dispuse a realizar las validaciones de la tienda online lo primero que busqué fue una solución rápida al problema, recordemos que se trataba en un principio de una práctica, y como tal, con una fecha de entrega; así que, lo que hice fue buscar alguna librería de JQuery que me solucionara el problema. Al realizar la búsqueda mi primer resultado fue Vanadium, y esa fue la que usé y la que os voy a explicar hoy aquí. Lo que, no quita que no haya otras librerías de validación.</p>
<p>Respecto a la librería que yo he utilizado llamada <a href="http://vanadiumjs.com/" target="_blank">VanadiumJS</a> cabe destacar la sencillez de su configuración además de que es fácilmente personalizable para adaptarla a nuestras necesidades. Vamos a ver como funciona.</p>
<p><span style="font-size: xx-large;"><strong>Instalación</strong></span></p>
<p><img class="alignleft size-full wp-image-1798" title="vanadiumFolder" src="http://blog.jdiezfoto.es/wp-content/uploads/2012/01/vanadiumFolder.png" alt="" width="219" height="90" />Para empezar, lo primero que haremos es explicar como hemos de configurar la librería e instalarla. Una buena manera de empezar sería crear un directorio en nuestra aplicación web para guardar archivos JavaScript. Y, en dicha carpeta tendríamos que guardar en primer lugar la librería de JQuery que podemos encontrar en su <a href="http://docs.jquery.com/Downloading_jQuery#Current_Release" target="_blank">web</a> y, después guardaríamos en ese mismo directorio la librería que vamos a usar que también la podeis descargar de la misma web de <a href="http://vanadiumjs.com/#download" target="_blank">VanadiumJS</a>.</p>
<p>Es importante colocar estas dos librerías de JavaScript debido a que Vanadium como era de esperar hace uso de JQuery.</p>
<p><img class="alignleft size-full wp-image-1799" title="cssFolder" src="http://blog.jdiezfoto.es/wp-content/uploads/2012/01/cssFolder.png" alt="" width="230" height="53" />Posteriormente, también deberíamos crear una carpeta para guardar hojas de estilos css, aunque posiblemente ya la hayamos creado para guardar nuestras propias hojas de estilos. Dentro de esta carpeta deberemos colocar una hoja de estilos <a href="https://github.com/lambder/Vanadium/blob/master/css/style.css" target="_blank">como esta</a>. Los estilos de esta hoja son los que serán aplicados a los formularios en caso de validación correcta o validación fallida.</p>
<p>Es una hoja de estilos sencilla de personalizar puesto que los nombres que llevan cada uno de los estilos son bastante intuitivos.</p>
<p>Finalmente toca hacer funcionar esto dentro de nuestros ficheros html estáticos o jsp u otros lenguajes. Esto será tan sencillo como importar todos estos archivos que hemos usado en la cabecera de cada fichero en la que lo queramos usar. Si esto nos resulta incómodo en el caso de jsp siempre podríamos hacer uso de la etiqueta import para no tener que poner estas líneas en todos los ficheros en los que se use.</p>
<pre class="brush: html; gutter: false; first-line: 1">&lt;head&gt;
	&lt;meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /&gt;
	&lt;title&gt;Login&lt;/title&gt;

	&lt;script type="text/javascript" src="/scripts/jquery-1.6.1.js"&gt;&lt;/script&gt;
	&lt;script type="text/javascript" src="/scripts/vanadium.js"&gt;&lt;/script&gt;

	&lt;link rel="stylesheet" type="text/css" href="/css/validacion.css" media="screen, tv, projection" /&gt;
&lt;/head&gt;</pre>
<p><span style="font-size: xx-large;"><strong>Validación en formularios</strong></span></p>
<p>En este apartado aprenderemos a llamar a esta librería para que haga las validaciones pertinentes en cada campo del formulario.</p>
<p>Vanadium usa el atributo <em>class</em> de los elementos de los formularios para que en él se escriban los ajustes que sean necesarios. Veamos un ejemplo sencillo con el que se validaría un campo de texto en el que se espera un e-mail.</p>
<pre class="brush: html; gutter: false; first-line: 1">&lt;input id="email" name="email" type="text" class=":email"/&gt;</pre>
<p>Se puede observar que hay un símbolo de dos puntos (:) al principio de cada ajuste. En este caso estaríamos indicando que se realizara una validación según la expresión regular de un email. Si hacemos la prueba de este código veremos que realiza la validación por cada evento que ocurre en la caja de texto, si no queremos este comportamiento se puede cambiar para que lo realice pasado un tiempo después de un evento o para que lo realice sólo cuando el campo se abandone (terminar de escribir y pasar al siguiente campo).</p>
<p>Otro aspecto importante es que en el ejemplo anterior se podría no escribir nada en la caja de texto y pasar la validación sin problemas, si se quiere que esto sea un campo requerido habría que usar otro ajuste. Veamos ahora un ejemplo más complejo.</p>
<p><strong>NOTA:</strong> En los códigos hay un espacio sobrante entre los dos puntos (:) y la o de &#8220;only_on_blur&#8221; debido a que se cambiaba por su correspondiente emoticono.</p>
<pre class="brush: html; gutter: false; first-line: 1">&lt;!--
email:validar email
required: campo obligatorio
only_on_blur: validar solo al abandonar el campo
--&gt;
&lt;input id="email" name="email" type="text" class=":email :required : only_on_blur"/&gt;

&lt;!--
wait;ms   Esperar una cantidad de milisegundos después de un evento para validar
--&gt;
&lt;input id="email" name="email" type="text" class=":email :required :wait;500"/&gt;</pre>
<p>También es posible la validación de otro tipo de campos a parte de el email que va vienen implementados por defecto con la librería. Podemos encontrar en la página web del proyecto una <a href="https://github.com/lambder/Vanadium/blob/master/doc/buildin_validation_types.txt" target="_blank">lista de las posibilidades admitidas</a>. Todos los ajustes que necesiten de un valor se indicará con el punto y coma (;) y después el valor, como se ha visto para el caso de wait.</p>
<p>Veamos por ejemplo como validar un campo típico en el que se pide que repitas la contraseña, para comprobar que has escrito lo mismo en los dos lugares.</p>
<pre class="brush: html; gutter: false; first-line: 1">Contraseña
&lt;input id="pass" name="pass" type="password" class=":password :required : only_on_blur"/&gt;

&lt;!--
Se usa el id del elemento que se quiere comprobar que es igual
--&gt;
Reescriba la contraseña por seguridad&lt;br /&gt;
&lt;input name="repeatPass" type="password" class=":same_as;pass :required : only_on_blur"/&gt;</pre>
<p><strong><span style="font-size: xx-large;">Personalizar los mensajes de error</span></strong></p>
<p>Puesto que es una librería escrita en inglés es de suponer que los mensajes de error que se produzcan cuando falle la validación esten en inglés, pero no hay problema, lo podemos cambiar. Para ello deberemos abrir el fichero JavaScript de Vanadium que hemos guardado en la carpeta de scripts, y luego nos dirigiremos a la línea 1012 aproximadamente.</p>
<p>Podremos ver estructuras repetitivas que llevan la expresión regular con la que se ha de validar, un nombre y un mensaje de error. Mostremos una de ejemplo.</p>
<pre class="brush: javascript; gutter: false; first-line: 1">['asciialpha', function (v) {
	return Vanadium.validators_types['empty'].test(v) || /^[a-zA-Z]+$/.test(v)   //% C0 - FF (� - �); 100 - 17E (? - ?); 391 - 3D6 (? - ?)
}, 'Please use ASCII letters only (a-z) in this field.'],</pre>
<p>Ahora si lo que queremos es que el mensaje se muestre en español sería tan sencillo como traducir el mensaje.</p>
<pre class="brush: javascript; gutter: false; first-line: 1">['asciialpha', function (v) {
	return Vanadium.validators_types['empty'].test(v) || /^[a-zA-Z]+$/.test(v)   //% C0 - FF (� - �); 100 - 17E (? - ?); 391 - 3D6 (? - ?)
}, 'Por favor, use solo caracteres ASCII (a-z) en este campo'],</pre>
<p>Como podemos ver es una tarea bastante sencilla.</p>
<p><span style="font-size: xx-large;"><strong>Personalizar los tipos de validaciones</strong></span></p>
<p>En este apartado veremos que también es posible añadir otros tipos de validaciones aparte de las que ya vienen implementadas por defecto con la librería, por ejemplo sería interesante una validación para direcciones postales.</p>
<p>Para esto nos situaremos en la zona del fichero JavaScript de Vanadium, aproximadamente por la línea 1012 y solo tendremos que repetir la estructura que ya hemos comentado en el apartado anterior pero personalizándola según nuestras necesidades. Mostraremos un ejemplo para validar una dirección de email; como se puede ver bastará con adaptar una expresión regular y personalizar nuestro mensaje.</p>
<pre class="brush: javascript; gutter: false; first-line: 1">['dir', function (v) {
	return Vanadium.validators_types['empty'].test(v) || /^[a-zA-Z0-9 \,\º\-\u00C0-\u00FF\u0100-\u017E\u0391-\u03D6]+\ [0-9]{5}-[a-zA-Z \-\u00C0-\u00FF\u0100-\u017E\u0391-\u03D6]+$/.test(v)   //% C0 - FF (� - �); 100 - 17E (? - ?); 391 - 3D6 (? - ?)
}, 'Introduzca una dirección válida'],</pre>
<p>Y posteriormente, en los formularios, bastará con usar el nombre que se le ha dado a la validación, en este caso &#8216;dir&#8217;.</p>
<pre class="brush: html; gutter: false; first-line: 1">&lt;input name="dir" type="text" class=":dir :required : only_on_blur"/&gt;</pre>
<p>También se pueden hacer cosas más complejas como se puede ver en líneas inferiores siguiendo la misma estructura.</p>
<p><span style="font-size: xx-large;"><strong>Validación usando la lógica del servidor por medio de AJAX y JSON</strong></span></p>
<p>En ocasiones no se pueden realizar todas las validaciones por medio del cliente, a veces se necesitan datos que solo se pueden obtener del servidor. El típico ejemplo de esto sería comprobar si una dirección de email ha sido ya usada anteriormente o no. Para este tipo de validaciones lo que se suele hacer es usar AJAX para realizar peticiones al servidor.</p>
<p>En el caso concreto de Vanadium nos va a permitir realizar una petición AJAX a la dirección que deseemos y el esperará un objeto <a href="http://es.wikipedia.org/wiki/JSON" target="_blank">JSON</a> como respuesta a dicha petición que indique si la validación ha sido correcta o no.</p>
<p>Lo primero que haremos será preparar un Servlet Java EE preparado para recibir peticiones en un determinado patrón de url personalizando este ajuste en el descriptor de despliegue.</p>
<pre class="brush: xml; gutter: false; first-line: 1">&lt;servlet&gt;
    &lt;servlet-name&gt;CheckEmailServlet&lt;/servlet-name&gt;
    &lt;servlet-class&gt;control.CheckEmailServlet&lt;/servlet-class&gt;
&lt;/servlet&gt;
&lt;servlet-mapping&gt;
    &lt;servlet-name&gt;CheckEmailServlet&lt;/servlet-name&gt;
    &lt;url-pattern&gt;/checkmail&lt;/url-pattern&gt;
&lt;/servlet-mapping&gt;</pre>
<p>Posteriormente en la implementación del Servlet lo primero que haremos es definir el tipo de respuesta como un objeto JSON y posteriormente abriremos el flujo de salida en el que escribiremos el JSON que espera Vanadium, que será como este que podemos observar en la <a href="https://github.com/lambder/Vanadium/blob/master/user_exists.json" target="_blank">web del proyecto</a>. Como vemos primero se indica si la validación fue válida y posteriormente un mensaje para mostrar en caso de error en la validación.</p>
<pre class="brush: text; gutter: false; first-line: 1">{
  success: true,
  message: "The username is free."
}</pre>
<p>mostremos ahora el código de un servlet sencillo que siempre devolverá la misma respuesta. Por supuesto hay que tener en cuenta que las escrituras en el flujo de salida deberían de ir en un <em>try</em> y realizar el cierre de la misma en un bloque <em>finally</em>. Como se puede observar simplemente se va construyendo el objeto JSON en el flujo de salida. Este Servlet en realidad no hace nada pero sería tan sencillo como devolver una u otra respuesta dependiendo de ciertas condiciones; que en nuestro ejemplo concreto sería comprobar si una dirección de email está usada o no.</p>
<pre class="brush: java; gutter: false; first-line: 1">response.setContentType("application/x-json;charset=UTF-8");
PrintWriter out = response.getWriter();
out.println ("{");
out.println("\"success\": false,");
out.println("\"message\": \"Dirección de email no disponible\"");
out.println("}");
out.close();</pre>
<p>Ahora habrá que configurar el campo del formulario que se desea validar al estilo de como se ha hecho en los ejemplos anteriores. Habrá que usar la opción ajax y después del punto y coma (;) habrá que indicar la dirección a la que se quiere realizar la petición. Veamos el ejemplo concreto.</p>
<pre class="brush: html; gutter: false; first-line: 1">&lt;input id="email" name="email" type="text" class=":email :required :ajax;/checkmail : only_on_blur"/&gt;</pre>
<p>Como vemos la directiva es bastante sencilla, simplemente se indica que se quiere hacer una validación vía AJAX y la dirección a la que se quiere hacer la petición, y como vemos es perfectamente combinable con cualquiera de las opciones ya vistas en apartados anteriores.</p>
<hr />
<p>Pues hasta aquí con este tutorial sobre el uso de la librería Vanadium para realizar validaciones de formularios en el lado del cliente usando JavaScript y JQuery. Comentar también que en la misma página de <a href="http://vanadiumjs.com/" target="_blank">Vanadium</a> es posible encontrar más ejemplos.</p>
<p>Espero que os haya sido útil este tutorial y mi parte nada más que decir; solamente deciros como siempre que están los comentarios a vuestra entera disposición para cualquier duda o sugerencia.</p>
<h4  class="related_post_title">También te puede interesar:</h4><ul class="related_post"><li><a href="http://blog.jdiezfoto.es/informatica/tienda-online-java-ee-solucionada-validacion-ajax-en-formulario-de-registro/" title="Tienda Online Java EE: Solucionada validación ajax en formulario de registro">Tienda Online Java EE: Solucionada validación ajax en formulario de registro</a></li><li><a href="http://blog.jdiezfoto.es/informatica/jrebel-stop-redeploying/" title="JRebel: Stop Redeploying">JRebel: Stop Redeploying</a></li><li><a href="http://blog.jdiezfoto.es/informatica/java-ee-seguridad-en-aplicaciones-web-ii-evitando-inyeccion-sql-y-xss-con-esapi/" title="Java EE: Seguridad en aplicaciones web (II). Evitando Inyección SQL y XSS con ESAPI">Java EE: Seguridad en aplicaciones web (II). Evitando Inyección SQL y XSS con ESAPI</a></li><li><a href="http://blog.jdiezfoto.es/informatica/tutorial-ant-uso-con-librerias-externas-y-generadores-jflex-y-cup/" title="Tutorial ANT: Uso con librerías externas y generadores JFlex y CUP">Tutorial ANT: Uso con librerías externas y generadores JFlex y CUP</a></li><li><a href="http://blog.jdiezfoto.es/informatica/java-ee-seguridad-en-aplicaciones-web-i/" title="Java EE: Seguridad en aplicaciones web (I)">Java EE: Seguridad en aplicaciones web (I)</a></li><li><a href="http://blog.jdiezfoto.es/informatica/java-ee-6-subida-de-imagenes-al-servidor-servlet-3-0/" title="Java EE 6: Subida de imágenes al servidor (Servlet 3.0)">Java EE 6: Subida de imágenes al servidor (Servlet 3.0)</a></li><li><a href="http://blog.jdiezfoto.es/informatica/ejemplo-javaee-una-tienda-online/" title="Ejemplo Java EE: Una tienda Online">Ejemplo Java EE: Una tienda Online</a></li></ul><p><p>© 2009-2011 Juan Díez-Yanguas Barber </p></p>]]></content:encoded>
			<wfw:commentRss>http://blog.jdiezfoto.es/informatica/vanadium-validacion-de-formularios-con-jquery/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Tienda Online Java EE: Solucionada validación ajax en formulario de registro</title>
		<link>http://blog.jdiezfoto.es/informatica/tienda-online-java-ee-solucionada-validacion-ajax-en-formulario-de-registro/</link>
		<comments>http://blog.jdiezfoto.es/informatica/tienda-online-java-ee-solucionada-validacion-ajax-en-formulario-de-registro/#comments</comments>
		<pubDate>Fri, 13 Jan 2012 20:46:11 +0000</pubDate>
		<dc:creator>Juan</dc:creator>
				<category><![CDATA[Informática]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[JavaScript]]></category>

		<guid isPermaLink="false">http://blog.jdiezfoto.es/?p=1769</guid>
		<description><![CDATA[<p>Para todos aquellos que no lo sepan, en este blog fue publicado hace tiempo un ejemplo de Java EE, una tienda online, pues bien, hoy vamos a comentar una pequeña actualización. Seguramente los que ya han usado el ejemplo y visto la documentación se habrán dado cuenta que la validación del lado del servidor usando <a href='http://blog.jdiezfoto.es/informatica/tienda-online-java-ee-solucionada-validacion-ajax-en-formulario-de-registro/' class='excerpt-more'>[...]</a></p><p><p>© 2009-2011 Juan Díez-Yanguas Barber </p></p>]]></description>
			<content:encoded><![CDATA[<p><img class="wp-image-1770 alignleft" title="registroOnlineShop" src="http://blog.jdiezfoto.es/wp-content/uploads/2012/01/registroOnlineShop.png" alt="" width="299" height="319" /></p>
<p>Para todos aquellos que no lo sepan, en este blog fue publicado hace tiempo un ejemplo de <a href="http://blog.jdiezfoto.es/informatica/ejemplo-javaee-una-tienda-online/">Java EE</a>, una tienda online, pues bien, hoy vamos a comentar una pequeña actualización.</p>
<p>Seguramente los que ya han usado el ejemplo y visto la documentación se habrán dado cuenta que la validación del lado del servidor usando ajax y JSON para comprobar en el registro que el email no estuviera en uso no funcionaba, como bien deje notificado.</p>
<p>Pues bien, después de tiempo intentando diversas cosas y mirando documentación del autor, ahora después de los examenes de enero he dado con el problema y lo he solucionado, la solución ha sido debidamente actualizada en el control de versiones y está disponible al público.</p>
<p>Más adelante explicaré detalladamente el tema de las validaciones con JavaScript en el cliente para que todos sepamos como han sido implementadas.</p>
<p>También, como sabéis el artículo fue publicado tambien en <a href="http://www.javahispano.org/portada/2011/10/23/ejemplo-de-aplicacion-java-ee-una-tienda-online.html" target="_blank">Javahispano</a>, comentar que para mi asombro, el artículo ha salido <a href="http://www.javahispano.org/portada/2012/1/3/top-10-contenido-mas-popular-en-javahispano-durante-2011.html" target="_blank">entre los 10 más populares de 2011</a>.</p>
<p>Espero que os haya gustado la notica, personalmente estoy contento porque es un tema que me ha traído bastante de cabeza.</p>
<h4  class="related_post_title">También te puede interesar:</h4><ul class="related_post"><li><a href="http://blog.jdiezfoto.es/informatica/vanadium-validacion-de-formularios-con-jquery/" title="Vanadium: Validación de formularios con JQuery">Vanadium: Validación de formularios con JQuery</a></li><li><a href="http://blog.jdiezfoto.es/informatica/jrebel-stop-redeploying/" title="JRebel: Stop Redeploying">JRebel: Stop Redeploying</a></li><li><a href="http://blog.jdiezfoto.es/informatica/java-ee-seguridad-en-aplicaciones-web-ii-evitando-inyeccion-sql-y-xss-con-esapi/" title="Java EE: Seguridad en aplicaciones web (II). Evitando Inyección SQL y XSS con ESAPI">Java EE: Seguridad en aplicaciones web (II). Evitando Inyección SQL y XSS con ESAPI</a></li><li><a href="http://blog.jdiezfoto.es/informatica/tutorial-ant-uso-con-librerias-externas-y-generadores-jflex-y-cup/" title="Tutorial ANT: Uso con librerías externas y generadores JFlex y CUP">Tutorial ANT: Uso con librerías externas y generadores JFlex y CUP</a></li><li><a href="http://blog.jdiezfoto.es/informatica/java-ee-seguridad-en-aplicaciones-web-i/" title="Java EE: Seguridad en aplicaciones web (I)">Java EE: Seguridad en aplicaciones web (I)</a></li><li><a href="http://blog.jdiezfoto.es/informatica/java-ee-6-subida-de-imagenes-al-servidor-servlet-3-0/" title="Java EE 6: Subida de imágenes al servidor (Servlet 3.0)">Java EE 6: Subida de imágenes al servidor (Servlet 3.0)</a></li><li><a href="http://blog.jdiezfoto.es/informatica/ejemplo-javaee-una-tienda-online/" title="Ejemplo Java EE: Una tienda Online">Ejemplo Java EE: Una tienda Online</a></li></ul><p><p>© 2009-2011 Juan Díez-Yanguas Barber </p></p>]]></content:encoded>
			<wfw:commentRss>http://blog.jdiezfoto.es/informatica/tienda-online-java-ee-solucionada-validacion-ajax-en-formulario-de-registro/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Java EE: Seguridad en aplicaciones web (II). Evitando Inyección SQL y XSS con ESAPI</title>
		<link>http://blog.jdiezfoto.es/informatica/java-ee-seguridad-en-aplicaciones-web-ii-evitando-inyeccion-sql-y-xss-con-esapi/</link>
		<comments>http://blog.jdiezfoto.es/informatica/java-ee-seguridad-en-aplicaciones-web-ii-evitando-inyeccion-sql-y-xss-con-esapi/#comments</comments>
		<pubDate>Tue, 13 Dec 2011 18:04:56 +0000</pubDate>
		<dc:creator>Juan</dc:creator>
				<category><![CDATA[Informática]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[seguridad]]></category>
		<category><![CDATA[sql]]></category>

		<guid isPermaLink="false">http://blog.jdiezfoto.es/?p=1639</guid>
		<description><![CDATA[<p>Después de un tiempo un poco más atareado por fin encuentro un hueco para cumplir mi promesa, vamos a continuar la guía de seguridad en aplicaciones web que se inició hace un tiempo. En esta nueva entrada se cubrirán en detalle los aspectos que quedaron por cubrir en la primera entrega: Inyección SQL y Cross <a href='http://blog.jdiezfoto.es/informatica/java-ee-seguridad-en-aplicaciones-web-ii-evitando-inyeccion-sql-y-xss-con-esapi/' class='excerpt-more'>[...]</a></p><p><p>© 2009-2011 Juan Díez-Yanguas Barber </p></p>]]></description>
			<content:encoded><![CDATA[<p><img class="aligncenter size-full wp-image-1405" title="OWASP" src="http://blog.jdiezfoto.es/wp-content/uploads/2011/10/OWASP.jpg" alt="" width="500" height="375" /></p>
<p>Después de un tiempo un poco más atareado por fin encuentro un hueco para cumplir mi promesa, vamos a continuar la <a href="http://blog.jdiezfoto.es/informatica/java-ee-seguridad-en-aplicaciones-web-i/">guía de seguridad en aplicaciones web</a> que se inició hace un tiempo. En esta nueva entrada se cubrirán en detalle los aspectos que quedaron por cubrir en la primera entrega: Inyección SQL y Cross Site Scripting (XSS). Aprenderemos a usar la librería <em>ESAPI</em> para evitar estos problemas de seguridad.</p>
<p><span id="more-1639"></span><span style="font-size: x-large;"><strong>Inyección SQL</strong></span></p>
<p>Comenzaremos hablando por el primero de los riesgos de seguridad que se comentaban en la entrada anterior. Para hacer un breve recordatorio veíamos que se trataba de intentar comprometer de alguna manera la base de datos de la aplicación.</p>
<p>Para ello, se suelen usar los formularios de las páginas web tratando de cerrar en ellos una consulta SQL e iniciando otra a continuación; dicho esto enviar directamente los datos de los formularios hacia una consulta SQL no es una buena práctica. Veremos en este apartado una serie de buenas prácticas que deberíamos llevar a cabo para evitar la inyección SQL.</p>
<p><span style="font-size: large;"><strong>Uso de PreparedStatements</strong></span></p>
<p>En primer lugar una muy buena práctica es cambiar el uso de los Statements por los PreparedStatements. Este tipo de Statement obliga a que la consulta tenga exactamente la estructura que se indica, y no deja que se cambie la estructura de la misma o se cierre una consulta y se abra otra nueva. También lleva a cabo un escapado de caracteres, puesto que podrías poner de nombre &#8220;O&#8217;Donnell&#8221; y no habría problema alguno en poner la comilla simple. Ni que decir tiene que también podríamos evitar la inyección SQL usando procedimientos almacenados.</p>
<p>Para hacer una consulta con un PreparedStatement lo primero que se hace es indicar la estructura de la consulta dejando los parámetros marcados con una interrogación &#8220;?&#8221; y posteriormente se irá indicando que son cada una de esas interrogaciones y su tipo de dato. Y gracias a que se indica el tipo de dato, Java ya se encarga de poner las comillas que hagan falta dependiendo del tipo de dato. Veremos que hay muchos métodos <em>set</em> dependiendo del tipo de dato a introducir.</p>
<p>Veamos un ejemplo. En el ejemplo se muestra un método sencillo para hacer un insert en la base de datos . He puesto el método completo para que también se observe una buena estructura para un método de este tipo. Siguiendo esta estructura es la mejor manera de asegurarse de que todos los recursos van a ser liberados en cualquier caso, tanto si se produce un error como si la ejecución es normal. Voy a explicar <a href="#anexo1">al final de esta entrada</a> en que consiste ese método <em>cerrarConexionYStatement ()</em>, ya que considero que es un punto importante a tener en cuenta para ahorrarnos unas cuantas líneas de código.</p>
<pre class="brush: java; gutter: true; first-line: 1; highlight: [8,10,11,12,13,15]">public boolean addUser(Usuario user) {
    Connection conexion = null;
    boolean exito = false;
    PreparedStatement insert = null;
    try {
        conexion = pool.getConnection();
		//Definir la estructura de la consulta
        insert = conexion.prepareStatement("INSERT INTO " + nameBD + ".Usuarios VALUES (?,?,?,?,?)");
		//Indicamos cada uno de los parámetros
        insert.setString(1, user.getMail());
        insert.setString(2, user.getNombre());
        insert.setString(3, user.getDir());
        insert.setString(4, user.getPass());
		//Incluso si no encontramos un método set para incluir un tipo de dato se puede personalizar como en este caso
        insert.setObject(5, user.getPermisos(), java.sql.Types.CHAR, 1);

        int filasAfectadas = insert.executeUpdate();
        if (filasAfectadas == 1) {
            exito = true;
        }
    } catch (SQLException ex) {
        logger.log(Level.SEVERE, "Error insertando usuario", ex);
    } finally {
        cerrarConexionYStatement(conexion, insert);
    }
    return exito;
}</pre>
<p>En el código de la <a href="http://blog.jdiezfoto.es/informatica/ejemplo-javaee-una-tienda-online/">tienda online</a> podemos encontrar numerosos métodos de este estilo y se pueden ver ejemplos en los que se use un ResultSet e incluso algún ejemplo en el que se realizan varias transacciones dependientes entre si y se realizan rollbacks y commits manualmente.</p>
<p>Hay que comentar que aunque no se vea siempre se realizan commits en todos los métodos, solo que por el hecho de ser consultas simples la conexión realiza los commit de manera automática, pero esto se puede cambiar como se puede ver en el código de la tienda online.</p>
<pre class="brush: java; gutter: false; first-line: 1">conexion.setAutoCommit(false);</pre>
<p><span style="font-size: large;"><strong>Realizar validaciones con expresiones regulares</strong></span></p>
<p>¿Esto es todo lo que podemos hacer? Pues no, podemos usar como medida de apoyo una validación de todos los datos de entrada de los usuarios en los formularios. Para realizar esta validación usaremos la librería que nos proporciona <a href="https://www.owasp.org/index.php/Main_Page" target="_blank">OWASP</a> que se hace denominar <a href="https://www.owasp.org/index.php/Category:OWASP_Enterprise_Security_API#tab=Java_EE" target="_blank">ESAPI</a>.</p>
<p>Y ahora como es lógico veremos como usar esta librería y configurarla. En primer lugar hemos de <a href="http://code.google.com/p/owasp-esapi-java/downloads/list" target="_blank">bajar el paquete</a> que nos proporcionan en el que se incluye en jar de ESAPI y todas las librerías que requiere ESAPI para funcionar (carpeta <em>libs</em> del paquete descargado). Hemos de añadir todas esas librerías a nuestro proyecto.</p>
<p>Una cosa importante. Entre las librerías requeridas es posible que se incluya la librería de servlets. Esa librería no la debéis de incluir en el proyecto puesto que es una versión más antigua de los Servlets y cambian métodos como por ejemplo la forma de acceder al contexto de la aplicación, por lo que nos interesa conservar la especificación de Servlets moderna que tenga nuestro servidor de aplicaciones.</p>
<p>La siguiente parte importante son los ficheros de configuración que necesita ESAPI para funcionar: <em>ESAPI.properties</em> y <em>validation.properties</em>. Podemos encontrar una plantilla de cada uno de los ficheros en el paquete descargado en <em>configuration/.esapi</em>.</p>
<p>La siguiente tarea es colocar los ficheros de configuración en un lugar adecuado para que se reconozcan. ESAPI buscará los ficheros en varios lugares en el orden en el que indico a continuación. Encontraremos esta información en la página de ESAPI o de la manera que lo he hecho yo que es mirando la consola del servidor de aplicaciones</p>
<pre class="brush: text; gutter: false; first-line: 1">INFO: Not found in 'org.owasp.esapi.resources' directory or file not readable: /Applications/NetBeans/glassfish-3.1/glassfish/domains/domain1/ESAPI.properties
INFO: Not found in SystemResource Directory/resourceDirectory: .esapi/ESAPI.properties
INFO: Not found in 'user.home' (/Users/Usuario) directory: /Users/Usuario/esapi/ESAPI.properties
INFO: Attempting to load ESAPI.properties via the classpath.</pre>
<p>En mi caso me pareció lo más cómodo incluirlo en el classpath. Para ello cree en la raiz del proyecto una carpeta llamada <em>setup</em>, que por otra parte es estándar que los proyectos web puedan tener esta carpeta para archivos de configuraciones, y posteriormente se ha de añadir dicha carpeta al classpath del proyecto.</p>
<p style="text-align: center;"><a href="http://blog.jdiezfoto.es/wp-content/uploads/2011/12/ClassPathOnlineShop.png" rel="lightbox[1639]"><img class="size-full wp-image-1647 aligncenter" title="ClassPathOnlineShop" src="http://blog.jdiezfoto.es/wp-content/uploads/2011/12/ClassPathOnlineShop.png" alt="" width="500" height="448" /></a></p>
<p>Una vez que hemos colocado los archivos en su lugar comenzaremos configurando cada uno de ellos. Lo que se va a configurar en estos ficheros principalmente serán las expresiones regulares que se van a usar para validar cada uno de los campos que deseemos.</p>
<p>El primer fichero que hemos nombrado, <em>ESAPI.properties</em> es un fichero que en lo que a nosotros nos concierne no hemos de tocar nada, la librería se sirve de él para hacer sus operaciones; nuestras personalizaciones irán en el segundo fichero nombrado. Pero no está de más echar un ojo al fichero para ver las validaciones que ya incluye y se verá que incluye validación para Email y alguna otra cosa más. Mirándolo también veremos cual es la forma de las expresiones regulares que admite.</p>
<p>Ahora pasemos al segundo fichero en el que hemos de configurar las expresiones regulares que consideremos necesarias. Para ello hemos de poner una clave y una atributo; al estilo de un fichero de propiedades. La clave será siempre <em>Validator.Campo</em>, siendo <em>Campo</em> lo que usaremos posteriormente para referirnos a esa expresión regular.</p>
<p>Esto no pretende ser un tutorial sobre como crear expresiones regulares, sin embargo haré algunas anotaciones. Si alguien necesita más ayuda con el tema puede preguntar y no tendré problema alguno en resolver sus dudas.</p>
<p>El símbolo &#8220;^&#8221; indica el inicio de la cadena, mientras que el símbolo &#8220;$&#8221; indica el final de la cadena. Es bueno escapar caracteres como el guión y el punto puesto que el guión se usa para indicar un rango y el punto significa cualquier cosa. Otra anotación importante es que a la hora de poner caracteres regionales debéis ponerlos con su correspondiente código en UTF-16; si no se hace de esta manera después puede que no funcione correctamente. Se puede encontrar una tabla de correspondencia básica en la <a href="http://es.wikipedia.org/wiki/Codificaci%C3%B3n_de_caracteres#Codificaci.C3.B3n_de_caracteres_del_espa.C3.B1ol" target="_blank">wikipedia</a>. Por ejemplo, si se quiere poner una &#8216;a&#8217; acentuada &#8220;á&#8221; se debe poner así <em>\u00e1</em>.</p>
<p>Si tenéis problemas con las expresiones regulares hay una <a href="http://www.regular-expressions.info/" target="_blank">web</a> que podéis usar que puede resultar interesante. También se puede usar un software específico para expresiones regulares que nos puede ayudar a crearlas en unos sencillos pasos y también nos ayudará a crearlas. Su nombre es <a href="http://www.regexbuddy.com/" target="_blank">RegexBuddy</a> y <a href="http://www.regexmagic.com/" target="_blank">RegexMagic</a>. El primero de ellos es sobretodo para aprender y verificar expresiones regulares mientras que el segundo está orientado a su creación.</p>
<p>Veamos ahora un pequeño ejemplo que son las que usé yo para la tienda online. Decir que no hace falta crear expresiones regulares para números porque tiene su verificación a parte que ya veremos.</p>
<pre class="brush: java; gutter: false; first-line: 1">Validator.Pss=^[A-Za-z0-9._$%&amp;/()= -#@áÁéÉíÍóÓúÚüÜñÑ]+$
Validator.Name=^[A-Z][a-zA-Z -áÁéÉíÍóÓúÚüÜñÑ]+$
Validator.Adress=^[A-Z][a-zA-Z0-9\-\ \,ºáÁéÉíÍóÓúÚüÜñÑ]+\ [0-9]{5}\-[A-Z][A-Za-z\ \-áÁéÉíÍóÓúÚüÜñÑ]+$
Validator.NameDescProd=^[A-Za-z0-9.,-_ @#%&amp;=áÁéÉíÍóÓúÚüÜñÑ¿?¡!]+$</pre>
<p>Una vez que estos ficheros han quedado correctamente configurados pasaremos ha explicar como han de usarse dentro de nuestra aplicación.</p>
<p>Veamos por ejemplo un método para validar un nombre usando la expresión regular que hicimos para validar un nombre. He dejado comentados cada uno de los argumentos necesarios y también se encuentra disponible el <a href="http://owasp-esapi-java.googlecode.com/svn/trunk_doc/latest/index.html" target="_blank">javadoc</a> en la página de los repositorios del proyecto o en el paquete descargado; por ejemplo puede existir un argumento más para que la cadena de caracteres se pase a forma canónica antes de ser validada.</p>
<pre class="brush: java; gutter: true; first-line: 1">public static String validateName(String input) throws IntrusionException, ValidationException {
    Validator validador = ESAPI.validator();
	//Nombre a referirse, entrada, nombre de la expresión regular, máxima longitud, permitir nulo o no
    return validador.getValidInput("Nombre", input, "Name", 100, false);
}</pre>
<p>El método devuelve la cadena validada y en caso de error hay dos tipos de excepciones, <em>ValidationException</em> es lanzada cuando simplemente no se ha pasado la validación, mientras que <em>IntrusionException</em> se lanza cuando se cree de manera muy clara que ha ocurrido un intento de ataque.</p>
<p>El primer argumento es un nombre para nuestro uso personal que posteriormente lo usará si hay un error para indicar donde ha ocurrido. Y el nombre de la expresión regular ha de ser el mismo que dimos en el fichero de propiedades, de esta manera se elige con que expresión regular se desea validar una entrada.</p>
<p>Como dije no hace falta crear expresiones regulares para los números puesto que usan validaciones a parte. Veamos un ejemplo.</p>
<pre class="brush: java; gutter: true; first-line: 1">public static int validateNumber(String input) throws IntrusionException, ValidationException {
    Validator validador = ESAPI.validator();
	//Nombe para referirse, entrada, mínimo, máximo, permitir nulo o no
    return validador.getValidInteger("Entero", input, 0, 999999, false);
}</pre>
<p>Como se puede ver en el ejemplo validar un número es tremendamente sencillo sin tener siquiera la necesidad de especificar una expresión regular para la validación de los mismos.</p>
<p>Ahora veremos un ejemplo de como usar estas validaciones dentro de nuestra aplicación.</p>
<pre class="brush: java; gutter: true; first-line: 1">try {
	String name = Tools.validateName(request.getParameter("name"));
} catch (IntrusionException ex) {
	request.setAttribute("resultados", "Detectada una intrusión");
	Tools.anadirMensaje(request, ex.getUserMessage());
} catch (ValidationException ex) {
	request.setAttribute("resultados", "Error en el formulario");
	Tools.anadirMensaje(request, ex.getUserMessage());
}</pre>
<p><span style="font-size: large;"><strong>Escapar las entradas de usuario</strong></span></p>
<p><em>ESAPI</em> también nos permitirá escapar las entradas del usuario para introducirlas en la base de datos; pero la verdad es que usando <em>PreparedStatements</em> este paso no sería necesario, y en caso de querer hacerlo habría que hacerlo después de pasar la validación por expresiones regulares puesto que al escapar una cadena se van a incluir nuevos caracteres como la contrabarra &#8220;\&#8221;. Veamos a continuación un ejemplo sencillo para escapar las entradas preparado especialmente para <em>MySQL</em> (<em>ESAPI</em> proporciona métodos de escape para <em>MySQL</em> y para <em>Oracle</em> si no recuerdo mal).</p>
<pre class="brush: java; gutter: true; first-line: 1">protected String scapeUserEntries (String input){
	Encoder encod = ESAPI.encoder();
	return encod.encodeForSQL(new MySQLCodec(MySQLCodec.MYSQL_MODE), input);
}</pre>
<p>Recomiendo que partiendo de los ejemplos y explicaciones que se han dejado aquí se eche un vistazo al javadoc de ESAPI puesto que contiene opciones bastante interesantes. Entre ellas tiene una forma de hacer validaciones seguidas poniendo los errores en una lista para hacer todo el conjunto de validaciones seguidas sin detenerse por el fallo de alguna de ellas.</p>
<p><span style="font-size: x-large;"><strong>Cross Site Scripting (XSS)</strong></span></p>
<p>Ahora que hemos visto como evitar las inyecciones SQL veremos ahora las formas de evitar Cross Site Scripting, que a modo de resumen a lo que se comentó en el <a href="http://blog.jdiezfoto.es/informatica/java-ee-seguridad-en-aplicaciones-web-i/">capítulo anterior</a> se podría decir que el fin que se persigue con este tipo de ataques es introducir alguna información en la base de datos para que posteriormente sea mostrada a otros usuarios. La información que se suele introducir serán scripts que persiguen realizar alguna actividad ilegítima.</p>
<p>De la misma manera que en el apartado anterior se validaban las entradas de los usuarios para evitar la inyección SQL realizando esa validación es evidente que se puede evitar también el XSS.</p>
<p>Aunque el problema puede venir de un caso en el que no queramos usar una expresión regular para validar, por ejemplo un campo de comentarios para el usuario en el que se permite cualquier caracter. En este caso lo que habrá que hacer es buscar etiquetas html sospechosas como <em>script</em>, pero&#8230; ¿realmente vale con buscar este tipo de etiquetas? Pues la respuesta es que no, porque si se usa otra codificación ya no van a aparecer así las etiquetas. A continuación veremos una buena forma de validar las entradas para evitar el XSS.</p>
<p><span style="font-size: large;"><strong>El problema de las codificaciones</strong></span></p>
<p>Lo primero veamos el problema de las codificaciones. En el siguiente ejemplo ambas líneas son equivalentes.</p>
<pre class="brush: html; gutter: true; first-line: 1">&lt;script&gt;alert("Este sitio es un peligro");&lt;/script&gt;
%3C%2Ftitle%3E%3Cscript%3Ealert%28%22%A1Este+Sitio+es+un+peligro%21%22%29%3C%2Fscript%3E</pre>
<p>Ahora si vemos que no se puede proteger simplemente buscando etiquetas html ¿no?. Por lo tanto lo primero que habrá que hacer es pasar la cadena a una forma canónica.</p>
<p>Obtener la forma canónica de una cadena consiste en convertir toda la cadena a una codificación conocida y admitida para que de esta manera se eviten problemas en la posterior validación.</p>
<p><span style="font-size: large;"><strong>Usando AntiSamy para validar entradas en HTML</strong></span></p>
<p>ESAPI también nos proporciona soluciones para todos los problemas comentados mediante un módulo llamado <em>AntiSamy</em>. Este se encarga de procesar código html y verificar si está permitido o por el contrario es un posible intento de intrusión, para ello usa un fichero xml de configuración en el que se especificarán con detalle las etiquetas html permitidas y no permitidas; también será posible especificar que tipo de propiedades de CSS se pueden usar.</p>
<p>El archivo xml de configuración de <em>AntiSamy</em> se puede colocar donde nosotros queramos, aunque, obviamente no sería una buena medida colocarlo en un directorio que sea accesible publicamente. En mi caso lo he colocado en el mismo sitio que los archivos de configuración de <em>ESAPI</em>, que si recordamos estaban en la carpeta <em>setup</em> que habíamos añadido al <em>classpath</em>.</p>
<p>En la <a href="https://www.owasp.org/index.php/Category:OWASP_AntiSamy_Project#Stage_2_-_Choosing_a_base_policy_file" target="_blank">página del proyecto de AntiSamy</a> es posible encontrar varios archivos de configuración de ejemplo, de más a menos restrictivos. Lo mejor es partir de alguno de estos archivos y en caso de querer modificarlos hacerlo observando las directivas que ya contiene puesto que no es una tarea sencilla hacer un archivo de estos desde cero, por ello nos proporcionan varios ejemplos. También hay un ejemplo en su <a href="http://code.google.com/p/owaspantisamy/downloads/list" target="_blank">página de descargas</a> muy interesante pensado para enviar datos al servidor que provienen de un TextArea con TinyMCE (Librería JQuery para dotar a un TextArea de un editor con WYSIWYG).</p>
<p>Ahora que hemos visto lo referente al fichero de configuración ya estamos en disposición de poner un ejemplo de un método que valida una entrada HTML. Este método que muestro a continuación valida una entrada que se le pasa como argumento y lanza una <em>IntrusionException</em> si la validación no ha pasado, dicha excepción la he lanzado yo para detectar los errores puesto que la librería no lanza excepciones ante una validación fallida, sino que anota los errores que han ocurrido y también tiene la posibilidad de eliminar aquello que no es válido según la configuración que hayamos hecho en el fichero xml.</p>
<p>Es importante ver también que como anoto en los comentarios antes de pasar la validación se obtiene la forma canónica del <em>String</em> usando un método que nos proporciona <em>ESAPI</em>. Y finalmente observar como se ha indicado donde esta el fichero xml de configuración, que se ha realizado usando el <em>classpath</em> y obteniendo su flujo de entrada.</p>
<pre class="brush: java; gutter: true; first-line: 1; highlight: [8,12]">public static void validateHTML(String input) {
    try {
		//No se admite una entrada vacía
        if (input.isEmpty() == true) {
            throw new IntrusionException("No se admite el campo vacío", "");
        }
		//Se obtiene el archivo de configuración a través del classpath
        Policy politica = Policy.getInstance(Tools.class.getResource("/antisamy-tinymce-1.4.4.xml"));
        AntiSamy validator = new AntiSamy();
		//Antes de analizar la cadena es convertida en su forma canónica
		//ESAPI.encoder().canonicalize(input)
        CleanResults cr = validator.scan(ESAPI.encoder().canonicalize(input), politica);

		//Si ha ocurrido un error se lanza una excepción indicando el error
        if (cr.getNumberOfErrors() != 0) {
            throw new IntrusionException("Ha introducido código HTML que no está permitido",
                    cr.getErrorMessages().get(0).toString());
        }
    } catch (PolicyException ex) {
        Logger.getLogger(Tools.class.getName()).log(Level.SEVERE, ex.getMessage());
    } catch (ScanException ex) {
        Logger.getLogger(Tools.class.getName()).log(Level.SEVERE, ex.getMessage());
    }
}</pre>
<p><a id="anexo1"> </a><br />
<span style="font-size: x-large;"><strong>Anexo &#8211; Cerrar Conexiones, Statements y ResultSets. Varargs en java</strong></span></p>
<p>En este apartado vamos a ver una buena manera de hacer esos métodos que decíamos para cerrar las conexiones y <em>Statments</em>. Aquí el problema viene de hacer un método que nos sirva para todos los métodos de la clase manejadora de la base de datos. No van a tener todos los métodos un <em>Statement</em> o un <em>ResultSet</em>, pueden tener varios de cada uno.</p>
<p>Se puede pensar en hacer métodos que reciban listas de Statements, pero estaríamos a lo mejor escribiendo líneas construyendo esas listas en cada método, líneas que se supone intentamos ahorrarnos. Pues bien java tiene algo llamado <em><a href="http://docs.oracle.com/javase/1.5.0/docs/guide/language/varargs.html" target="_blank">varargs</a></em> para facilitarnos esta tarea, aunque internamente este construyendo listas el caso es que no tenemos que construirlas nosotros.</p>
<p>Lo único que hemos de hacer es colocar en la cabecera de los métodos de cierre unos puntos suspensivos detrás del tipo de dato. El argumento que vaya con <em>varargs</em> debe ser el último y debe haber solo uno (esto es debido a que sino java no tiene forma de saber los tipos de datos de los argumentos). Posteriormente dentro del método podemos recorrer los elementos con un bucle <em>for-each</em>, como si de un lista normal se tratara (que es de hecho lo que hace internamente como ya he dicho).</p>
<pre class="brush: java; gutter: true; first-line: 1; highlight: [1,7,19,20]">private void cerrarConexionYStatement(Connection conexion, Statement... statements) {
    try {
        conexion.close();
    } catch (SQLException ex) {
        logger.log(Level.SEVERE, "Error al cerrar una conexión a la base de datos", ex);
    } finally {
        for (Statement statement : statements) {
            if (statement != null) {
                try {
                    statement.close();
                } catch (SQLException ex) {
                    logger.log(Level.SEVERE, "Error al cerrar un statement", ex);
                }
            }
        }
    }
}

private void cerrarResultSet(ResultSet... results) {
    for (ResultSet rs : results) {
        if (rs != null) {
            try {
                rs.close();
            } catch (SQLException ex) {
                logger.log(Level.SEVERE, "Error al cerrar un resultset", ex);
            }
        }
    }
}</pre>
<p>Estos métodos podrían admitir toda una serie de llamadas no dependiendo del número de <em>Statement</em> o <em>ResultSet</em>.</p>
<pre class="brush: java; gutter: false; first-line: 1">cerrarConexionYStatement(conexion, select);
cerrarConexionYStatement(conexion, deleteHistorialCarros, deleteProdCarro);

cerrarResultSet(rs);
cerrarResultSet(consultaDatosCarro, rs);</pre>
<p>Como podemos suponer nos hemos ahorrado bastantes líneas en cada uno de los métodos, ahora como máximo habrá dos líneas en cada método para cerrar los recursos independientemente del número de recursos que haya.</p>
<hr />
<p>Bueno, y hasta aquí esta guía de seguridad para aplicaciones web junto con el uso de ESAPI que como vemos llega a ser muy útil para las tareas de seguridad en nuestra aplicación.</p>
<p>También comentar que puede venir bien la lectura de los consejos que nos da OWASP para los dos problemas que hemos tratado en esta entrada (en inglés): <a href="https://www.owasp.org/index.php/SQL_Injection_Prevention_Cheat_Sheet" target="_blank">Inyección SQL</a> y <a href="https://www.owasp.org/index.php/XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet" target="_blank">Cross Site Scripting (XSS)</a>.</p>
<p>Comentar que todo lo que hemos aprendido en estos dos capítulos se refiera a la lógica de servidor como es evidente, esta lógica siempre debe existir, pero debo comentar que si se realizan validaciones en el cliente por ejemplo usando JavaScript se puede quitar un poco de carga al servidor, ya que ante una validación fallida esa petición no llegará al servidor.</p>
<p>Espero que os hayan sido útiles estas guías de seguridad, y como siempre digo a vuestra disposición quedo para cualquier duda problema o sugerencia.</p>
<h4  class="related_post_title">También te puede interesar:</h4><ul class="related_post"><li><a href="http://blog.jdiezfoto.es/informatica/ejemplo-javaee-una-tienda-online/" title="Ejemplo Java EE: Una tienda Online">Ejemplo Java EE: Una tienda Online</a></li><li><a href="http://blog.jdiezfoto.es/informatica/java-ee-seguridad-en-aplicaciones-web-i/" title="Java EE: Seguridad en aplicaciones web (I)">Java EE: Seguridad en aplicaciones web (I)</a></li><li><a href="http://blog.jdiezfoto.es/informatica/presentacion-sobre-seguridad-en-aplicaciones-web/" title="Presentación sobre seguridad en aplicaciones web">Presentación sobre seguridad en aplicaciones web</a></li><li><a href="http://blog.jdiezfoto.es/informatica/jrebel-stop-redeploying/" title="JRebel: Stop Redeploying">JRebel: Stop Redeploying</a></li><li><a href="http://blog.jdiezfoto.es/informatica/vanadium-validacion-de-formularios-con-jquery/" title="Vanadium: Validación de formularios con JQuery">Vanadium: Validación de formularios con JQuery</a></li><li><a href="http://blog.jdiezfoto.es/informatica/tienda-online-java-ee-solucionada-validacion-ajax-en-formulario-de-registro/" title="Tienda Online Java EE: Solucionada validación ajax en formulario de registro">Tienda Online Java EE: Solucionada validación ajax en formulario de registro</a></li><li><a href="http://blog.jdiezfoto.es/informatica/tutorial-ant-uso-con-librerias-externas-y-generadores-jflex-y-cup/" title="Tutorial ANT: Uso con librerías externas y generadores JFlex y CUP">Tutorial ANT: Uso con librerías externas y generadores JFlex y CUP</a></li></ul><p><p>© 2009-2011 Juan Díez-Yanguas Barber </p></p>]]></content:encoded>
			<wfw:commentRss>http://blog.jdiezfoto.es/informatica/java-ee-seguridad-en-aplicaciones-web-ii-evitando-inyeccion-sql-y-xss-con-esapi/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Tutorial ANT: Uso con librerías externas y generadores JFlex y CUP</title>
		<link>http://blog.jdiezfoto.es/informatica/tutorial-ant-uso-con-librerias-externas-y-generadores-jflex-y-cup/</link>
		<comments>http://blog.jdiezfoto.es/informatica/tutorial-ant-uso-con-librerias-externas-y-generadores-jflex-y-cup/#comments</comments>
		<pubDate>Mon, 28 Nov 2011 10:35:36 +0000</pubDate>
		<dc:creator>Juan</dc:creator>
				<category><![CDATA[Informática]]></category>
		<category><![CDATA[Java]]></category>

		<guid isPermaLink="false">http://blog.jdiezfoto.es/?p=1517</guid>
		<description><![CDATA[<p>He dedicado tiempo ultimamente a aprender al menos de manera básica el uso ANT, que para los que no lo sepan es una herramienta para compilación de proyectos JAVA al estilo del make para C. Justo me proponen en la universidad que realice una presentación en clase sobre ello; no me ha podido venir más <a href='http://blog.jdiezfoto.es/informatica/tutorial-ant-uso-con-librerias-externas-y-generadores-jflex-y-cup/' class='excerpt-more'>[...]</a></p><p><p>© 2009-2011 Juan Díez-Yanguas Barber </p></p>]]></description>
			<content:encoded><![CDATA[<p><a href="http://ant.apache.org/projects.html"><img class="aligncenter size-full wp-image-1526" title="AntLogo" src="http://blog.jdiezfoto.es/wp-content/uploads/2011/11/AntLogo.png" alt="Logo Ant" width="554" height="343" /></a></p>
<p>He dedicado tiempo ultimamente a aprender al menos de manera básica el uso ANT, que para los que no lo sepan es una herramienta para compilación de proyectos JAVA al estilo del <em>make</em> para C. Justo me proponen en la universidad que realice una presentación en clase sobre ello; no me ha podido venir más bien después de haber estado yo haciendo algunos ejemplos. Así que me dispuse a ordenar mis investigaciones para crear un ejemplo sencillo que aunara lo que considero más importante, y sobre ese ejemplo realizar una presentación que me ayudara a explicarlo en clase de la manera más ordenada posible.</p>
<p>Bueno, y ya que he hecho la presentación y el ejemplo pues me animo también a presentar aquí el tutorial</p>
<p><span id="more-1517"></span></p>
<p><span style="font-size: xx-large;"><strong>¿Qué es ANT?</strong></span></p>
<p>Como ya he comentado <a href="http://ant.apache.org/projects.html" target="_blank">ANT</a> es una herramienta para compilación de proyectos JAVA, y como tal escrita en el mismo. Se podría decir que es una herramienta como <a href="http://es.wikipedia.org/wiki/Make" target="_blank">make</a> para programas en C solo que especialmente diseñada pensando en JAVA; nos proporciona los medios para la realización de las tareas que componen el proceso de compilación, documentación, distribución, etc de un proyecto JAVA.</p>
<p>Es muy útil para los casos en los que se trabaja con distintos entornos de desarrollo para disponer de una manera estándar y fácil de compilar el proyecto, y sobretodo en proyectos complejos con muchas librerías o en proyectos web en los que las tareas de compilación comprenden más pasos. Además la mayoría de los entornos de desarrollo disponen de opciones para la ejecución de scripts de ANT.</p>
<p>Por último comentar que actualmente no es ant la herramienta más usada para esto, sino que se está usando cada vez más una herramienta similar llamada <a href="http://maven.apache.org/" target="_blank">Maven</a>, la cual tiene algunas ventajas sobre el que ahora nos ocupa.</p>
<p><strong style="font-size: xx-large;">Instalación de ANT</strong></p>
<p>La instalación de ANT es bien sencilla, básicamente consiste en situar los archivos de ant en las variables de entorno del sistema. Podemos conseguir los archivos de instalación en la <a href="http://ant.apache.org/bindownload.cgi" target="_blank">web del proyecto</a>. Pese a ser una obviedad comentaré que se necesita tener instalado el JDK (Java Developer Kit) puesto que ant está escrito en Java.</p>
<p><strong><span style="font-size: x-large;">Mac OS</span></strong></p>
<p>Yo no he tenido que hacer nada para instalarlo, o viene por defecto o se instaló con el Xcode de Mac OS.</p>
<p><strong><span style="font-size: x-large;">Linux</span></strong></p>
<p>Si suponemos que hemos situado los archivos ANT en /usr/local/ant</p>
<pre class="brush: bash; gutter: false; first-line: 1">export ANT_HOME=/usr/local/ant
export JAVA_HOME=/usr/local/jdk-1.5.0.05
export PATH=${PATH}:${ANT_HOME}/bin</pre>
<p><strong><span style="font-size: x-large;">Windows</span></strong></p>
<p>Si suponemos que hemos situado los archivos de ANT en C:\ant\</p>
<pre class="brush: shell; gutter: false; first-line: 1">set ANT_HOME=c:\ant
set JAVA_HOME=c:\jdk-1.5.0.05
set PATH=%PATH%;%ANT_HOME%\bin</pre>
<p>Si hemos instalado ant correctamente podremos teclear el comando para ver su versión en la consola y nos deberá reconocer el comando.</p>
<p>Para ejecutar ant sobre un fichero build.xml nos situaremos en el directorio donde este el fichero y teclearemos ant para ejecutar el objetivo por defecto o ant y un objetivo en concreto para ejecutar ese objetivo concreto (se ejecutarán también sus dependencias obviamente)</p>
<pre class="brush: shell; gutter: false; first-line: 1">#Obtener la versión instalada de ant
$ant -version

#Ejecutar un script de ant con el objetivo por defecto
$ant

#Ejecutar un script de ant con el objetivo que elijamos
$ant objetivo</pre>
<p><span style="font-size: xx-large;"><strong>Algunas definiciones</strong></span></p>
<p>Vamos a ver en este apartado algunos conceptos que hemos de conocer para trabajar con ANT.</p>
<p>Mientras que en el famoso make de C teníamos un fichero llamado makefile, en este caso tendremos un fichero xml llamado build.xml en el que estarán escritos los pasos que se han de seguir para la compilación de nuestro proyecto. Pasemos ahora a definir los elementos de dicho fichero (o etiquetas puesto que es un fichero XML).</p>
<ul>
<li><em>project</em>: Es el elemento raíz del fichero XML y como tal solo puede haber uno en el fichero. Es el propio proyecto con el que estamos trabajando</li>
<li><em>target</em>: Elemento que agrupa un conjunto de tareas que se desean realizar en un momento determinado. Como veremos puede haber unos objetivos dependientes de otros</li>
<li><em>task</em>: Es el código ejecutable que será aplicado a la aplicación en algún momento, puede contener distintas propiedades.</li>
<li><em>property</em>: Parámetros en forma de par clave-valor (los nombres serán case-sensitive) para personalizar el proceso de construcción o simplemente como accesos directos a un dato que se use de manera repetitiva en el fichero xml.</li>
</ul>
<p>Continuemos ahora viendo una estructura de directorios para un proyecto Java.<br />
<img class="alignleft size-full wp-image-1536" title="estructuraProyectoJava" src="http://blog.jdiezfoto.es/wp-content/uploads/2011/11/estructuraProyectoJava.png" alt="Estructura Proyecto Java" width="147" height="132" /> En primer lugar tenemos el directorio <em>classes</em> en donde se almacenarán las clases Java compiladas.</p>
<p>Dentro del directorio <em>dist</em> se encontrará la aplicación empaquetada en forma de jar autoejecutable, también se podía incluir aquí la documentación para su distribución aunque he optado por ponerla en la raíz del proyecto.</p>
<p>En el directorio <em>doc</em> estará la documentación del proyecto en formato javadoc.</p>
<p>En el interior del directorio <em>lib</em> estarán almacenadas las bibliotecas externas que hayamos usado en nuestro proyecto.</p>
<p>Por último el directorio <em>src</em> en el que estará el código fuente de la aplicación organizado en los paquetes que hayamos decidido nosotros mismos.</p>
<p><strong style="font-size: xx-large;">Nuestro primer build.xml</strong></p>
<p>Vamos a ver aquí nuestro primer ejemplo y sobre él explicaremos las partes básicas a parte de las etiquetas ya explicadas.</p>
<pre class="brush: xml; gutter: true; first-line: 1">&lt;project name="ProbandoAnt" default="compilar" basedir="."&gt;

	&lt;!-- propiedades globales del proyecto --&gt;
	&lt;property name="fuente" value="scr" /&gt;
	&lt;property name="destino" value="classes" /&gt;

	&lt;!-- Objetivo --&gt;
	&lt;target name="compilar"&gt;
		&lt;!-- Tarea --&gt;
		&lt;javac srcdir="${fuente}" destdir="${destino}" /&gt;
	&lt;/target&gt;

&lt;/project&gt;</pre>
<p>Lo primero que nos encontramos es que la raiz del fichero tiene dos atributos que no hemos explicado anteriormente. El primero de ellos es <em>default</em>, este especifica cual es el objetivo que se ejecutará por defecto al ejecutar este script de ant salvo que se especifique uno concreto. El atributo <em>basedir</em> indica donde están situados los directorios del proyecto. En este caso como tendremos el fichero buid.xml al mismo nivel que los directorios del proyecto hemos puesto un punto.</p>
<p>Lo siguiente que nos encontraremos serán las propiedades que como dije son pares clave valor. En este caso yo las he usado para tener un acceso más rápido a los distintos directorios y menos problemas si alguno de ellos fuera cambiado. Accederemos a ellas posteriormente así ${propiedad}</p>
<p>Finalmente nos encontramos con un objetivo sencillo que realiza la compilación con la tarea <em>javac</em>, tiene como atributos <em>srcdir</em> que indica donde está el código fuente a compilar y <em>destdir</em> indica en que directorio se han de dejar las clases compiladas.</p>
<p>Los objetivos pueden tener dependencias, las cuales se indican con el atributo <em>depends</em>. Las dependencias entre objetivos indican que un objetivo que depende de otro no será ejecutado sin que se haya ejecutado previamente ese otro del que depende. Veamos un ejemplo sencillo</p>
<pre class="brush: xml; gutter: true; first-line: 1">&lt;!-- El objetivo empaqueta no será ejecutado sin antes ejecutar el objetivo compila.
O dicho de otra manera el objetivo empaqueta obliga a que se ejecute primero el objetivo compila --!&gt;

&lt;target name="empaqueta" depends="compila"&gt;

&lt;/target&gt;

&lt;target name="compila"&gt;  

&lt;/target&gt;</pre>
<p><strong><span style="font-size: xx-large;">Empaquetado del proyecto</span></strong></p>
<p>En este apartado veremos como crear un objetivo que se encargue de empaquetar las clases compiladas en un único jar autoejecutable.</p>
<p>Un archivo jar es como un archivo zip, incluso con la misma compresión; y en su interior contiene las clases java organizadas en paquetes y una carpeta más llamada META-INF, esa carpeta es la usada para meter en su interior meta-información sobre el archivo jar.</p>
<p>Dentro de la carpeta nombrada se suele encontrar un fichero llamado manifest.mf, el cual tiene en su interior un conjunto de pares clave valor que pueden ser necesarios. En nuestro ejemplo lo que indicaremos en el fichero será cual es la clase main (<em>Main-Class</em>) de nuestro proyecto para que se sepa por donde tiene que empezar la ejecución. Sin esto no podríamos ejecutar el archivo jar, al menos con el típico doble click, habría que hacerlo pasando por la consola y llamando directamente a la clase Main.</p>
<pre class="brush: xml; gutter: true; first-line: 1">&lt;target name="empaquetar" depends="compilar"&gt;
	&lt;jar destfile="${dist}/ejemploant.jar" basedir="${destino}" includes="**"&gt;
		&lt;manifest&gt;
			&lt;attribute name="Built-By" value="${user.name}" /&gt;
			&lt;attribute name="Main-Class" value="ejemploant.ejemploant" /&gt;
		&lt;/manifest&gt;
	&lt;/jar&gt;
&lt;/target&gt;</pre>
<p>Como hemos visto, la tarea jar contiene dos atributos, el primero de ellos llamado <em>destfile</em> que indicará la ruta donde queremos el fichero jar generado, el atributo <em>basedir</em> indica donde se encuentran las clases compiladas a incluir y finalmente el atributo <em>includes</em> que me indicará que tipo de ficheros se incluyen dentro del fichero jar creado.</p>
<p>Como se puede ver, un nivel por debajo de la tarea jar nos encontramos con la etiqueta <em>manifest</em>, la cual, como podemos suponer, sirve para incluir conjuntos de pares clave valor dentro del fichero que comenté anteriormente. Como se observa se indica la ruta a la clase main tal y como hemos comentado.</p>
<p><strong style="font-size: xx-large;">Generación de documentación</strong></p>
<p>En este apartado veremos como crear un objetivo que cree documentación <em>javadoc</em> sobre nuestro proyecto. Vamos a poner aquí un pequeño ejemplo y lo explicaremos posteriormente.</p>
<pre class="brush: xml; gutter: true; first-line: 1">&lt;target name="documentar"&gt;
	&lt;javadoc packagenames="*"
		sourcepath="${fuente}"
		destdir="${javadoc}"
		author="true"
		version="true"
		private="true"
		locale="es"
		windowtitle="Prueba de ANT"
		doctitle="Prueba de ANT"
		bottom="Jdyb Copyright 2011"&gt;
	&lt;/javadoc&gt;
&lt;/target&gt;</pre>
<p>Como vemos la tarea que se encarga de generar la documentación javadoc del proyecto tiene bastantes atributos, los primeros de ellos son los más importantes de todos. El primero de ellos, <em>packagenames</em>, indica los paquetes sobre los que se desea generar la documentación, esta vez hemos puesto asterisco para generar la documentación de todos ellos, <em>sourcepath</em> es el directorio donde se encuentran los archivos fuente del proyecto, <em>destdir</em> indica el directorio donde se van a guardar los archivos generados en el proceso de documentación (el resultado final).</p>
<p>Los demás atributos que observamos son de menos importancia que los anteriores ya que se refieren más a la personalización de esa documentación a generar, por ejemplo tomar en cuenta etiquetas <em>@author</em> o <em>@version</em>, el título y el pie de página del documento, etc&#8230;</p>
<p><strong style="font-size: xx-large;">Limpieza e Inicialización</strong></p>
<p>Entre las muchas tareas predefinidas con las que cuenta ant podemos encontrar tareas para crear y borrar carpetas (y archivos).</p>
<p>Puede ser que queramos borrar las clases compiladas antes de una nueva compilación para que no haya problemas, y obviamente también habrá que crear las carpetas después de borrarlas.</p>
<p>Veamos aquí dos ejemplos de objetivos de ejemplo para crear y borrar carpetas. En este ejemplo haremos que se borre el paquete jar autoejecutable, las clases compiladas y la documentación generada; parece lo más lógico hacerlo así para evitar problemas si hay cambios grandes en la estructura de clases y paquetes.</p>
<pre class="brush: xml; gutter: true; first-line: 1">&lt;target name="limpiar"&gt;
	&lt;delete dir="${destino}" /&gt;
	&lt;delete dir="${javadoc}" /&gt;
	&lt;delete dir="${dist}" /&gt;
&lt;/target&gt;

&lt;target name="init" depends="limpiar"&gt;
	&lt;mkdir dir="${destino}" /&gt;
	&lt;mkdir dir="${javadoc}" /&gt;
	&lt;mkdir dir="${dist}" /&gt;
&lt;/target&gt;</pre>
<p>Como podemos ver la tarea <em>delete</em> tiene como función borrar directorios y con los atributos se indica que es lo que se quiere borrar. Y, con la tarea <em>mkdir</em> se hace lo contrario, crear directorios.</p>
<p>Como podeis ver el objetivo <em>init</em> depende del objetivo limpiar. Lo que quiere decir que llamar al objetivo <em>init</em> impicará borrar todo lo anterior y dejar las carpetas listas para la compilación, empaquetado y generación de documentación.</p>
<p><strong style="font-size: xx-large;">Utilización con librerías externas</strong></p>
<p>En este apartado veremos como trabajar con librerías externas y veremos como hacer las tareas que ya hemos realizado pero usando librerías externas.</p>
<p>Es posible hacer referencia a una carpeta con librerías de varias formas, pero si se quiere usar esa referencia en varios lugares del fichero build.xml la mejor forma es hacer uso del elemento <em>path</em>, dentro del cual se selecciona la carpeta con las librerías, pudiéndose también hacer uso de filtros para seleccionar solo determinados ficheros.</p>
<pre class="brush: xml; gutter: true; first-line: 1">&lt;path id="path.libs"&gt;
	&lt;pathelement location="." /&gt;
	&lt;fileset dir="lib"&gt;
		&lt;include name="**/*.jar" /&gt;
	&lt;/fileset&gt;
&lt;/path&gt;</pre>
<p>Posteriormente habrá que usar ese elemento para incluirlo en el classpath durante la compilación y la generación de la documentación</p>
<pre class="brush: xml; gutter: false; first-line: 1">&lt;classpath refid="path.libs" /&gt;</pre>
<p>Y en lo que respecta a la tarea del empaquetado de las clases compiladas hay que tener en cuenta dos cosas, en primer lugar para incluir un fichero jar de librerías en el paquete autoejecutable jar generado lo que se realiza es una descompresión del jar de las librerías para incluirlo en el jar final. Como resultado de este proceso obtendríamos la carpeta META-INF del paquete de las librerías, que de no ser excluido sobreescribiría la carpeta META-INF junto con el manifiesto creado, por lo que se perdería la meta-información que añadíamos a nuestro fichero jar final, y si esta información se perdiese la máquina virtual de JAVA no sabría cual es la clase Main para ejecutar el paquete.</p>
<p>Por lo tanto, para realizar estas tareas usaremos el elemento <em>zipfileset</em> indicando el fichero comprimido a incluir junto con un filtro para excluir la carpeta META-INF como ya hemos dicho.</p>
<pre class="brush: xml; gutter: true; first-line: 1">&lt;target name="empaquetar" depends="compilar"&gt;
	&lt;jar destfile="${dist}/ejemploant.jar" basedir="${destino}" includes="**"&gt;
		&lt;manifest&gt;
			&lt;attribute name="Built-By" value="${user.name}" /&gt;
			&lt;attribute name="Main-Class" value="ejemploant.ejemploant" /&gt;
		&lt;/manifest&gt;
		&lt;zipfileset src="lib/jdom.jar" excludes="META-INF/*" /&gt;
	&lt;/jar&gt;
&lt;/target&gt;</pre>
<p><strong><span style="font-size: xx-large;">Ejecución</span></strong></p>
<p>En este apartado veremos como ejecutar el proyecto tanto desde una clase java como desde el proyecto empaquetado en un jar.</p>
<p><strong><span style="font-size: x-large;">Ejecución desde clase Java</span></strong></p>
<p>La tarea que nos ayudará a la ejecución es <em>java</em>, y usaremos el atributo <em>classname</em> para indicar la clase a ejecutar, para que pueda encontrar dicha clase tendremos que definir el atributo <em>classpath</em> con la ruta donde esta el paquete y la clase que hemos dicho que tenga que ejecutar.</p>
<p>Para poner los argumentos tendremos que usar <em>arg</em> y el argumento se pondrá en el atributo <em>value</em>. También hay que tener en cuenta que habrá que indicar la ruta de las librerías referenciando al elemento <em>path</em> que creamos en el apartado anterior.</p>
<pre class="brush: xml; gutter: true; first-line: 1">&lt;target name="run" depends="compilar" description="Ejecutar aplicacion con clase java" &gt;
	&lt;java classname="ejemploant.ejemploant" classpath="${destino}"&gt;
		&lt;arg value="build.xml"/&gt;
		&lt;classpath refid="path.libs" /&gt;
	&lt;/java&gt;
&lt;/target&gt;</pre>
<p><strong><span style="font-size: x-large;">Ejecución desde un archivo jar</span></strong></p>
<p>Para este caso seguiremos usando la tarea java pero en este caso con el atributo jar en el que indicaremos la ubicación del archivo jar a ejecutar. Recordemos que para que la máquina virtual de java (VM) sepa que clase tiene que ejecutar tendremos que haber definido bien las propiedades en el manifiesto como ya explicamos anteriormente.</p>
<p>Es obligatorio el uso del atributo <em>fork</em> puesto que para ejecutar este jar la VM creará una nueva instancia. Como opción podemos usar el atributo <em>maxmemory </em>para indicar la máxima memoria que se reservará para la nueva instancia de la VM.</p>
<p>El resto será igual que en el caso anterior indicando los argumentos y añadiendo al <em>classpath</em> el elemento <em>path</em> que se definió anteriormente.</p>
<pre class="brush: xml; gutter: true; first-line: 1">&lt;target name="runjar" depends="empaquetar" description="Ejecutar aplicacion de archivo jar" &gt;
	&lt;java jar="${dist}/ejemploant.jar" fork="true" maxmemory="128m"&gt;
		&lt;arg value="build.xml"/&gt;
		&lt;classpath refid="path.libs" /&gt;
	&lt;/java&gt;
&lt;/target&gt;</pre>
<p><strong><span style="font-size: xx-large;">Usando ANT con JFlex y CUP</span></strong></p>
<p>Como consecuencia de haber preparado la presentación para una asignatura sobre procesamiento de lenguajes vamos a tener un apartado extra en este tutorial. Este añadido tratará sobre como automatizar la utilización de Jflex (Generador de analizadores léxicos) y CUP (Generador de analizadores sintácticos).</p>
<p>Pues bien, lo primero que tendremos que hacer es decargar las librerías de <a href="http://jflex.de/jflex-1.4.3.zip" target="_blank">JFlex</a> y <a href="http://www2.cs.tum.edu/projects/cup/java-cup-11a.jar" target="_blank">CUP</a> para situar sendos Jar en la carpeta de librerías.</p>
<p>Conviene saber que ambos generadores contienen en el interior de sus librerías una tarea de ant, por lo que nuestro trabajo consistirá únicamente en usar dichas tareas.</p>
<pre class="brush: xml; gutter: false; first-line: 1">&lt;taskdef classpathref="path.libs" classname="JFlex.anttask.JFlexTask" name="jflex" /&gt;
&lt;taskdef classpathref="path.libs" classname="java_cup.anttask.CUPTask" name="cup" /&gt;</pre>
<p>Como vemos usamos el elemento <em>taskdef</em> y como atributos señalamos la carpeta de librerías que ya habíamos definido anteriormente en el apartado donde veíamos como usar librerías externas, posteriormente indicamos la clase en la que se encuentra esa tarea de ant y finalmente se indica el nombre bajo el que se usará esa tarea en el documento build.xml.</p>
<p>Mostramos ahora un objetivo encargado de la generación de los analizadores y posteriormente pasaremos a explicar cada uno de los atributos usados.</p>
<pre class="brush: xml; gutter: true; first-line: 1">&lt;target name="generateGrammar"&gt;
	&lt;jflex file="${grammar}/reglas.flex" destdir="${fuente}"/&gt;
	&lt;cup srcfile="${grammar}/Gram.cup" destdir="${fuente}"/&gt;
&lt;/target&gt;</pre>
<p><span style="font-size: large;"><strong>JFlex</strong></span></p>
<p>En lo que se refiere a la tarea de <em>jflex</em> contamos con el atributo <em>file</em> en el cual se indica el fichero flex del que se partirá para la generación del analizador léxico, y finalmente <em>destdir</em> que indica el directorio en el que se generará el fichero java generado organizado en paquetes según se indique en el fichero flex.</p>
<p><span style="font-size: large;"><strong>CUP</strong></span></p>
<p>En la tarea de CUP tenemos el atributo <em>srcfile</em>, equivalente al <em>file</em> de Jflex y <em>destdir </em>también equivalente al atributo del mismo nombre en Jflex. También se pueden usar otros atributos como <em>interface</em> para crear una interfaz java en vez de una clase. CUP también producirá su salida organizada en el paquete que se haya especificado en el fichero cup.</p>
<p><strong style="font-size: xx-large;">Recursos</strong></p>
<p>Como parte de este tutorial dejaré aquí la presentación a modo de resumen y un proyecto de ANT como ejemplo.</p>
<p>En el proyecto de ejemplo se ha creado un objetivo de ant para explicar su uso, por lo que si queremos saber las opciones que tiene este fichero de configuración habrá que usar la siguiente orden en la consola situados en la carpeta del proyecto.</p>
<pre class="brush: xml; gutter: false; first-line: 1">$ant usage</pre>
<ul>
<li><a href="http://blog.jdiezfoto.es/wp-content/uploads/2011/11/PresentacionANT.pdf">Presentación en pdf</a></li>
<li><a href="http://blog.jdiezfoto.es/wp-content/uploads/2011/11/EjemploANT.zip">Proyecto de ejemplo</a></li>
</ul>
<hr />
<p>Hasta aquí este tutorial sobre ANT. Espero que os haya sido de utilidad, como siempre digo quedo abierto a todo tipo de sugerencias o adiciones; tenéis los comentarios a vuestra disposición.</p>
<h4  class="related_post_title">También te puede interesar:</h4><ul class="related_post"><li><a href="http://blog.jdiezfoto.es/informatica/jrebel-stop-redeploying/" title="JRebel: Stop Redeploying">JRebel: Stop Redeploying</a></li><li><a href="http://blog.jdiezfoto.es/informatica/vanadium-validacion-de-formularios-con-jquery/" title="Vanadium: Validación de formularios con JQuery">Vanadium: Validación de formularios con JQuery</a></li><li><a href="http://blog.jdiezfoto.es/informatica/tienda-online-java-ee-solucionada-validacion-ajax-en-formulario-de-registro/" title="Tienda Online Java EE: Solucionada validación ajax en formulario de registro">Tienda Online Java EE: Solucionada validación ajax en formulario de registro</a></li><li><a href="http://blog.jdiezfoto.es/informatica/java-ee-seguridad-en-aplicaciones-web-ii-evitando-inyeccion-sql-y-xss-con-esapi/" title="Java EE: Seguridad en aplicaciones web (II). Evitando Inyección SQL y XSS con ESAPI">Java EE: Seguridad en aplicaciones web (II). Evitando Inyección SQL y XSS con ESAPI</a></li><li><a href="http://blog.jdiezfoto.es/informatica/java-ee-seguridad-en-aplicaciones-web-i/" title="Java EE: Seguridad en aplicaciones web (I)">Java EE: Seguridad en aplicaciones web (I)</a></li><li><a href="http://blog.jdiezfoto.es/informatica/java-ee-6-subida-de-imagenes-al-servidor-servlet-3-0/" title="Java EE 6: Subida de imágenes al servidor (Servlet 3.0)">Java EE 6: Subida de imágenes al servidor (Servlet 3.0)</a></li><li><a href="http://blog.jdiezfoto.es/informatica/ejemplo-javaee-una-tienda-online/" title="Ejemplo Java EE: Una tienda Online">Ejemplo Java EE: Una tienda Online</a></li></ul><p><p>© 2009-2011 Juan Díez-Yanguas Barber </p></p>]]></content:encoded>
			<wfw:commentRss>http://blog.jdiezfoto.es/informatica/tutorial-ant-uso-con-librerias-externas-y-generadores-jflex-y-cup/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Java EE: Seguridad en aplicaciones web (I)</title>
		<link>http://blog.jdiezfoto.es/informatica/java-ee-seguridad-en-aplicaciones-web-i/</link>
		<comments>http://blog.jdiezfoto.es/informatica/java-ee-seguridad-en-aplicaciones-web-i/#comments</comments>
		<pubDate>Mon, 31 Oct 2011 23:03:37 +0000</pubDate>
		<dc:creator>Juan</dc:creator>
				<category><![CDATA[Informática]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[seguridad]]></category>

		<guid isPermaLink="false">http://blog.jdiezfoto.es/?p=1404</guid>
		<description><![CDATA[<p>Hace ya unos meses, publiqué una presentación que hice en la universidad sobre seguridad en las aplicaciones web, en concreto con Java EE. Ahora lo que me dispongo a hacer es repasar las partes más importantes de aquella charla en incluso aportar alguna cosa más sobre el tema después de haber estado trabajando con ello <a href='http://blog.jdiezfoto.es/informatica/java-ee-seguridad-en-aplicaciones-web-i/' class='excerpt-more'>[...]</a></p><p><p>© 2009-2011 Juan Díez-Yanguas Barber </p></p>]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.jdiezfoto.es/wp-content/uploads/2011/10/OWASP.jpg" rel="lightbox[1404]"><img class="aligncenter size-full wp-image-1405" title="OWASP" src="http://blog.jdiezfoto.es/wp-content/uploads/2011/10/OWASP.jpg" alt="" width="500" height="375" /></a></p>
<p>Hace ya unos meses, publiqué una presentación que hice en la universidad sobre <a href="http://blog.jdiezfoto.es/informatica/presentacion-sobre-seguridad-en-aplicaciones-web/" target="_blank">seguridad en las aplicaciones web</a>, en concreto con Java EE. Ahora lo que me dispongo a hacer es repasar las partes más importantes de aquella charla en incluso aportar alguna cosa más sobre el tema después de haber estado trabajando con ello en la <a href="http://blog.jdiezfoto.es/informatica/ejemplo-javaee-una-tienda-online/" target="_blank">tienda online</a>. Al ser un tema bastante amplio será distribuido entre varios artículos.</p>
<p>En esta serie de artículos aprenderemos a usar las herramientas que nos proporcionan las librerías de la empresa <a href="https://www.owasp.org/index.php/Main_Page" target="_blank">OWASP</a>. También aprovecharemos para fijarnos en sus consejos ya que se dedican a estudiar entre otras cosas los problemas que yo voy a nombrar aquí.</p>
<p><span id="more-1404"></span><span style="font-size: x-large;"><strong>Introducción &#8211; Principios de seguridad</strong></span></p>
<p>Antes de nada vamos a dar una guía de buenas prácticas que es interesante conocer antes de empezar a construir aplicaciones para conseguir un trabajo lo más bueno posible.</p>
<ul>
<li><strong>No dar nunca nada por hecho</strong> ni en cuestiones de seguridad ni en cuestiones del flujo normal de la aplicación. Todo el riesgo que se corra debe ser por parte del usuario (no hay nada que hacer contra eso). Me explico, no supongamos que si le pido el nombre al usuario no me va a poner un número de teléfono. No se si sería una forma acertada de decirlo pero hay que pensar con pesimismo, en los peores casos, y por remotos que sean pueden ocurrir.</li>
</ul>
<ul>
<li><strong>Siempre que usemos servicios externos estamos asumiendo riesgos añadidos</strong>. Podemos haber hecho una página web muy segura y muy bien construida, pero si incrustamos contenido externo nadie nos asegura que el contenido externo sea vulnerable a algún tipo de ataque.</li>
</ul>
<ul>
<li><strong>La oscuridad no es seguridad</strong>. No poner un botón acceso a la administración no impide que se pueda acceder a ella. Ocultar nuestro código no debe ser parte de nuestra seguridad.</li>
</ul>
<ul>
<li><strong>Principio del mínimo privilegio:</strong> El usuario del sistema debe tener únicamente los privilegios que necesita para llevar a cabo su actividad.</li>
</ul>
<ul>
<li><strong>Fallar de manera segura:</strong> Hay que tratar de manera muy cuidadosa los fallos en la aplicación. Por poner un ejemplo, si se produce un fallo en la aplicación mientras se realizan tareas administrativas no debe seguir iniciada la sesión como administrador. Otro ejemplo, no debe mostrar en un fallo información técnica sobre el mismo al usuario del sistema. Si el usuario sabe datos acerca de nuestro sistema podría tener más fácil la búsqueda de vulnerabilidades.</li>
</ul>
<p><span style="font-size: x-large;"><strong>Los riesgos</strong></span></p>
<p>Ahora que hemos dado unos pequeños consejos sobre seguridad a la hora de la construcción de aplicaciones ya podemos pasar a explicar los riesgos que hay en las aplicaciones web. No vamos a ponernos a programar nada sin saber los riesgos existentes y el porque de las medidas que se toman para combatirlos.</p>
<p>Voy a nombrar aquí los riesgos que considero más importantes.</p>
<ul>
<li><strong>Inyección SQL:</strong> Consiste en intentar &#8220;engañar&#8221; al sistema para que realice peticiones contra la base de datos que no son las que han sido programadas y que podrían comprometer gravemente la base de datos o incluso mostrar al atacante toda la información de la misma.</li>
</ul>
<ul>
<li><strong>Cross Site Scripting:</strong> El atacante intentará enviar información a nuestro servidor por medio de nuestros formularios u otros medios con la intención de que dicha información sea almacenada en nuestra base de datos y posteriormente sea mostrada a los demás usuarios del sistema. Un ejemplo sencillo: Un código JavaScript que borre el contenido de la página, si eso es mostrado a los demás usuarios de la aplicación verán siempre una página en blanco. Esto es un ejemplo sencillo, pero imaginarios que lo que se consigue introducir es un código que tome el control de los navegadores de los usuarios de la aplicación web.</li>
</ul>
<ul>
<li><strong>Robo de sesión:</strong> Como sabemos HTTP es un protocolo sin estados, lo que significa que las credenciales o información de sesión deberá ir en cada petición; debido a esto dichos datos resultan muy expuestos. Un robo de estos datos podría tener como resultado que alguien se estuviera haciendo pasar por nosotros y realizando acciones con unos privilegios que nos pertenecen. Y tampoco hemos de olvidar que se pude robar la sesión intentando obtener nuestros credenciales de alguna manera (averiguar nuestra contraseña).</li>
</ul>
<ul>
<li><strong>Acceso a URLs restringidas:</strong> Consiste en la observación de una URL e intentar cambiarla para intentar acceder a otras zonas. Estas es una de las razones por las que la seguridad a través de la ocultación no es efectiva.</li>
</ul>
<p><span style="font-size: x-large;"><strong>Solucionando los problemas de seguridad</strong></span></p>
<p>Ahora que ya hemos identificado y visto en que consisten los problemas que nos podemos encontrar en las aplicaciones web, o al menos lo más importantes y peligrosos vamos a ir uno por uno explicando como hemos de solucionarlos. Iremos primero a los dos últimos que son los más sencillos y en posteriores entradas explicaremos la solución a los dos primeros que son los más importantes de los cuatro y quiero dedicarles una entrada completa.</p>
<p><span style="font-size: large;"><strong>Robo de sesión</strong></span></p>
<p>Ya hemos visto el riesgo que tiene el robo de una sesión. Podríamos decir de manera resumida que el peligro está en la exposición de los datos de sesión. En la ilustración de la presentación de seguridad que hice podemos ver una posible situación de robo de sesión.</p>
<p style="text-align: center;"><a href="http://blog.jdiezfoto.es/wp-content/uploads/2011/10/RoboSesion.jpg" rel="lightbox[1404]"><img class="aligncenter size-full wp-image-1418" title="RoboSesion" src="http://blog.jdiezfoto.es/wp-content/uploads/2011/10/RoboSesion.jpg" alt="" width="614" height="461" /></a></p>
<p>Para solucionar este problema de seguridad hay que atenerse a varios aspectos de la seguridad: la autentificación y la sesión; para cada uno de ellos veremos varios aspectos importantes a cubrir para solucionar problemas con el robo de sesión.</p>
<p><strong><span style="font-size: medium;">La Autentificación</span></strong></p>
<ul>
<li>El más importante de todos. Usar SSL sobre HTTP (HTTPS) para transferir los datos y asegurarse de que el cifrado cubre los credenciales y el ID de sesión en todas las comunicaciones. De esta manera los datos de sesión de los que hablábamos siguen estando expuestos pero esta vez se encuentran cifrados, por lo que no se pueden usar. Alguien podría pensar: &#8220;¿Y si se obtiene la sesión y se rompe la encriptación?&#8221;, la respuesta es sencilla, y es que con los medios actuales para cuando hayas conseguido romper la encriptación esa sesión habrá dejado de existir.</li>
</ul>
<ul>
<li>Usar un sistema de autentificación simple, centralizado y estandarizado. Es mejor que usemos métodos de autentificación que nos proporcione el propio servidor de aplicaciones en vez de soluciones implementadas por nosotros, debido a que lo que implementa el servidor de aplicaciones es usado en muchos lugares y ha sido suficientemente probado. Por ejemplo los filtros de Java EE (que veremos posteriormente) o los métodos de autentificación que proporciona Java EE (no los he usado).</li>
</ul>
<ul>
<li>Posibilitar el bloqueo de autentificación después de un número determinado de intentos fallidos. Esto podría evitar ataques de fuerza bruta intentando averiguar la contraseña del usuario.</li>
</ul>
<ul>
<li>Implementar métodos seguros de recuperación de contraseñas: Es común que se intenten usar estos métodos para intentar ganar acceso a una cuenta del usuario, podemos ver una serie de consejos para implementar estos métodos. Pedir al usuario al menos tres datos o más, obligar a que responda preguntas de seguridad. La contraseña que recuperada deberá generarse de manera aleatoria (con una longitud de al menos 8 caracteres) y enviada al usuario por un canal diferente (E-mail); de esta forma si el atacante consiguió sortear los primeros pasos es difícil que logre sortear el canal usado para transmitir.</li>
</ul>
<p><strong><span style="font-size: medium;">La Sesión</span></strong></p>
<ul>
<li>Usar los métodos de sesión que nos proporciona el servidor de aplicaciones que estemos usando, y digo esto por las mismas razones que aconsejé usar los métodos de autentificación que proporciona el servidor de aplicaciones. En este caso no estamos refiriendo a la sesión y a las cookies.</li>
</ul>
<ul>
<li>Asegurar que la operación de cierre de sesión realmente destruye dicha sesión. También fijar el periodo de expiración de la sesión (periodo de tiempo en el que no se realice ninguna acción bajo dicha sesión); por ejemplo para aplicaciones críticas de 2 a 5 minutos, mientras que para otras aplicaciones más comunes se podría usar de 15 a 30 minutos.</li>
</ul>
<p>En el descriptor de despliegue podemos fijar la caducidad de la sesión en minutos.</p>
<pre class="brush: xml; gutter: true; first-line: 1">&lt;session-config&gt;
    &lt;session-timeout&gt;15&lt;/session-timeout&gt;
&lt;/session-config&gt;</pre>
<p>Ahora que hemos visto las formas de evitar el robo de sesión; o al menos de manera teórica, ahora vamos a ver como se hacen esta serie de cosas en la práctica.</p>
<p>Hemos hablado de usar métodos proporcionados por el servidor de aplicaciones para realizar la autenticación usando filtros y la sesión. Vamos a ver en concreto como podría hacerse. En primer lugar habrá que comprobar si los datos de usuario son correctos y posteriormente se podría hacer algo como añadir algún parámetro a la sesión indicando que esta autenticada. Voy a simplificar mucho un código para que nos centremos en lo fundamental.</p>
<pre class="brush: java; gutter: true; first-line: 1">if (password.equals(user.getPass()) == true) {
	//Se añade a la sesión un boolean indicando que está autentificado
	request.getSession().setAttribute("auth", true);

	//Se añade a la sesión el identificador del usuario
	request.getSession().setAttribute("usuario", user.getMail());
}</pre>
<p>Respecto a bloquear el inicio de sesión después de un número determinado de intentos fallidos podría ser tan fácil como añadir a la sesión el número de intentos fallidos y en el caso de que superen un determinado número no ejecutar ningún mecanismo de autenticación ni mostrar el formulario de login, únicamente habría que lanzar un timer para desbloquear el inicio de sesión pasado un tiempo.</p>
<pre class="brush: java; gutter: true; first-line: 1">protected void starTimer(final HttpSession sesion) {
	//Tarea que se lanzará cuando el Timer la ejecute
    TimerTask timerTask = new TimerTask() {

        @Override
        public void run() {
            sesion.invalidate();
        }
    };

    Timer timer = new Timer ();
	//El tiempo esta en milisegundos y se lanza la tarea que definimos anteriormente
    timer.schedule(timerTask, 600000);
}</pre>
<p>Luego, para comprobar este parámetro (el que se ha añadido a la sesión para comprobar si se ha autentificado o no) sería factible usar filtros para todas las URLs para las que se necesite permiso y en ellos comprobar si existe el parámetro añadido en la sesión o no.</p>
<p>Lo primero de todo en el descriptor de despliegue (web.xml) hemos de configurar el filtro. Definiremos el filtro para un patrón de URL, en este caso todas las estén dentro del directorio /admin. Como sabemos los filtros actúan ante las peticiones de cliente para los patrones de URL para los que estén definidos. ¿Es esto del todo cierto? Pues no, en Java EE 6 esto ha cambiado un poco y podemos especificar que un filtro se ejecute sin necesidad de que el cliente haga una petición, simplemente con que el servidor haga una redirección porque así lo especifique el código (repito, sin que el cliente tenga nada que ver y sin que sepa nada de esa redirección). Podemos hacer esto mediante las sentencias que he dejado resaltadas.</p>
<pre class="brush: xml; gutter: true; first-line: 1; highlight: [9,10,11,12,13]">&lt;!-- Filtro de zona privada--&gt;
&lt;filter&gt;
	&lt;filter-name&gt;AdminFilter&lt;/filter-name&gt;
	&lt;filter-class&gt;control.admin.AdminFilter&lt;/filter-class&gt;
&lt;/filter&gt;

&lt;filter-mapping&gt;
	&lt;filter-name&gt;AdminFilter&lt;/filter-name&gt;
	&lt;url-pattern&gt;/admin/*&lt;/url-pattern&gt;
	&lt;dispatcher&gt;REQUEST&lt;/dispatcher&gt;
	&lt;dispatcher&gt;FORWARD&lt;/dispatcher&gt;
	&lt;dispatcher&gt;INCLUDE&lt;/dispatcher&gt;
	&lt;dispatcher&gt;ERROR&lt;/dispatcher&gt;
&lt;/filter-mapping&gt;</pre>
<p>Ahora veremos la clase que implementa el filtro y veremos que es a la misma clase a la que se hace referencia en el descriptor de despliegue. En ella simplemente se comprueba la existencia de los parámetros que se añadieron a la sesión en el proceso de autenticación. Los nombres de las variables son claros por lo que no he hecho comentarios, me parece que se ve claro el objetivo del código</p>
<p>Unicamente comentar que un Servlet no es exclusivo de una aplicación web, un ServletHttp es una clase de Servlet especial por así decirlo, de ahí que con el ServletRequest que nos da el filtro no podamos obtener la sesión y por eso necesitamos la primera línea del  método doFilter en la que se hace un casting.</p>
<pre class="brush: java; gutter: true; first-line: 1; highlight: [21,22,28,33]">package control.admin;

import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

/**
 * @author Juan Díez-Yanguas Barber
 */
public class AdminFilter implements Filter {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
		//Obtenemos un HttpServletRequest con un casting
        HttpServletRequest requestMod = ((HttpServletRequest) request);
        if (isPermited(requestMod) == false){
            requestMod.getSession().setAttribute("requestedPage", requestMod.getRequestURL().toString());
            RequestDispatcher noPermited = request.getRequestDispatcher("/WEB-INF/paginasError/restricted.jsp");
            noPermited.forward(request, response);
        }else{
			//Continua la secuencia de ejecución normal
            chain.doFilter(request, response);
        }
    }

    private boolean isPermited(HttpServletRequest request) {
        if (request.getSession().getAttribute("auth") == false || request.getSession().getAttribute("usuario") == null) {
            return false;
        } else{
            return true;
        }
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    @Override
    public void destroy() {
    }
}</pre>
<p>Ahora veremos como cerrar la sesión de la manera más correcta. Lo más correcto sería destruir la sesión, de esta manera nuestra sesión dejará de existir a todos los efectos. Para ello usaremos la siguiente sentencia, cuya función es destruir la sesión. La podríamos usar por ejemplo en un Servlet encargado del cierre de sesión.</p>
<pre class="brush: java; gutter: true; first-line: 1">request.getSession().invalidate();</pre>
<p>Respecto al tema de las contraseñas voy a dedicar al final de esta entrada un apartado donde explicaré como trabajar correctamente con ellas.</p>
<p><span style="font-size: large;"><strong>Acceso a URLs restringidas</strong></span></p>
<p>Como ya hemos visto en el apartado teórico sobre este problema la seguridad a través de la ocultación no sirve de nada. Si por ejemplo para la parte pública se usara un patrón de URL /public el atacante podría pensar que la parte privada pudiera ser /admin o cosas parecidas, con no dar a conocer el detalle de ese directorio no es suficiente, hay que protegerlo.</p>
<p>Como a estas alturas supondremos no hay que hacer nada especial si se ha realizado lo anterior, es decir, si hemos realizado una autenticación y un control de sesión correctos. Con el uso de los filtros podríamos solucionar este problema perfectamente.</p>
<p>Se que es un problema que a la vista parece bastante evidente y con una solución sencilla; pero mientras siga apareciendo como uno de los problemas más graves de seguridad será porque no está tan bien solucionado aunque sea evidente el problema y la solución.</p>
<p><span style="font-size: x-large;"><strong>Trabajando correctamente con contraseñas</strong></span></p>
<p>Las contraseñas son un dato delicado, la palabra secreta que usa el usuario para acceder a su cuenta en el sitio web, algo suyo y <strong>personal</strong>. Por este motivo únicamente el usuario debería conocer su contraseña. Ahora bien, si solo conoce él la contraseña&#8230; ¿Cómo la comprobamos cuando inicie sesión? Vamos a ver que si que es posible hacerlo sin conocer la contraseña; lo haremos usando una huella digital <a href="http://en.wikipedia.org/wiki/MD5" target="_blank">MD5</a> o <a href="http://en.wikipedia.org/wiki/SHA-1" target="_blank">SHA1</a> (he puesto los enlaces en inglés, me parecían más completos).</p>
<p>En definitiva estos dos son los algoritmos más usados para la generación de huellas digitales, consistentes en crear una suma siempre de igual longitud independientemente del tamaño del mensaje y con la particularidad de que no se puede volver al mensaje original a partir del mensaje encriptado; pero un mismo mensaje siempre genera el mismo código.</p>
<pre class="brush: java; gutter: true; first-line: 1">//Método para generar la huella MD5
public static String generateMD5Signature(String input) {
    try {
		//Cambiando MD5 por SHA-1 podríamos obtener la huella usando este otro algoritmo
        MessageDigest md = MessageDigest.getInstance("MD5");
        byte[] huella = md.digest(input.getBytes());
        return transformaAHexadecimal(huella);
    } catch (NoSuchAlgorithmException ex) {
        Logger.getLogger(Tools.class.getName()).log(Level.SEVERE,
                "No se ha encontrado el algoritmo MD5", ex);
        return "-1";
    }
}

//Método para transformar el array de bytes en una cadena hexadecimal
private static String transformaAHexadecimal(byte buf[]) {
    StringBuilder strbuf = new StringBuilder(buf.length * 2);
    for (int i = 0; i &lt; buf.length; i++) {
        if (((int) buf[i] &amp; 0xff) &lt; 0x10) {
            strbuf.append("0");
        }
        strbuf.append(Long.toString((int) buf[i] &amp; 0xff, 16));
    }
    return strbuf.toString();
}</pre>
<p>A sabiendas de lo anterior podríamos darnos cuenta de que si en vez de guardar la contraseña de los usuarios guardamos la huella digital de la misma podremos verificar su identidad cuando él inicie sesión, y no tendremos su contraseña guardada ni modo alguno de obtenerla. Lo que habrá que hacer es obtener la huella de su contraseña cuando el usuario la introduzca y la compararemos con la huella que nosotros teníamos guardada.</p>
<p>Así estaremos protegiendo al usuario; si nuestra base de datos se viese comprometida y llegamos a tener guardadas las contraseñas todos nuestros usuarios estarían expuestos, mientras que de esta manera que explico esto no ocurriría.</p>
<p>¿Es este método infalible? Pues no, existen tablas de huellas de palabras clave que se suelen usar, ya se sabe que no solemos ser bastante ocurrentes poniendo las palabras clave (solemos usar 1234, password, etc&#8230;), así que si disponen de una tabla de este tipo podrían obtener las contraseñas a partir de las huellas de nuestra base de datos comprometida (si bien no obtendrán todas, alguna seguro que sí).</p>
<p>Pues bien, aún con estos problemas nos quedan armas a usar. Si en vez de guardar las huellas de las contraseñas, guardamos las huellas de las contraseñas sumado con algo más. Si obtienen el mensaje que formó esa huella con una tabla de esas obtendrían la contraseña más eso que añadimos nosotros, luego no obtienen la contraseña. Y esto podría admitir muchas variaciones, como poner caracteres por enmedio de la contraseña, al final, al principio, lo que se añada a la contraseña podría ser tan complejo como desearamos. Pero sin olvidarse que al comprobar la contraseña habrá que hacer el mismo proceso.</p>
<p>Vamos a ver un ejemplo sencillo, mostraremos como se introduce la contraseña cuando el usuario se registra y como se comprueba cuando inicia sesión. En este caso vamos a añadir al final de la contraseña el nombre de usuario del sistema (Podría haber problemas si se cambiara el nombre de usuario en la máquina, pero no me voy a centrar en eso ahora, esto pretende ser solo un ejemplo ilustrativo).</p>
<pre class="brush: java; gutter: true; first-line: 1">String pass = request.getParameter("pass");
pass = Tools.generateMD5Signature(pass + System.getProperty("user.name"));</pre>
<p>Veamos ahora el proceso de comprobación (user será el usuario que tenemos guardado ya en la base de datos y del cual tenemos su huella de la contraseña más el añadido).</p>
<pre class="brush: java; gutter: true; first-line: 1">String pass = request.getParameter("pass");
if (Tools.generateMD5Signature(password + System.getProperty("user.name")).equals(user.getPass()) == true) {
	//Contraseña correcta
} else {
	//Contraseña incorrecta
}</pre>
<p>Ahora la cuestión viene cuando hacemos un método para recuperar la contraseña, no la podemos recuperar de forma alguna, no la hemos guardado. Por lo tanto, lo que habrá que hacer es generar una nueva y asignarla al usuario y mandarle la nueva contraseña por correo.</p>
<pre class="brush: java; gutter: true; first-line: 1">//Como argumento la longitud de la contraseña
String newPass = RandomStringUtils.randomAlphanumeric(19);
String newPassHash = Tools.generateMD5Signature(newPass + System.getProperty("user.name"));
//Asignar newPassHash al usuario</pre>
<p>Hasta aquí llegamos con este artículo, como ya he comentado, trataré los otros problemas de seguridad de artículos posteriores. Espero que os haya sido de utilidad y os ayude a hacer aplicaciones web más seguras. También podeis encontrar más información en la web de <a href="https://www.owasp.org/index.php/Authentication_Cheat_Sheet" target="_blank">OWASP sobre la autentificación</a> y sobre más cosas que hemos estado tratando.</p>
<p>Digo lo mismo de siempre, estoy a vuestra disposición para dudas, comentarios o lo que sea; por supuesto también podeis aportar alguna otra cosa que consideréis interesante.</p>
<h4  class="related_post_title">También te puede interesar:</h4><ul class="related_post"><li><a href="http://blog.jdiezfoto.es/informatica/java-ee-seguridad-en-aplicaciones-web-ii-evitando-inyeccion-sql-y-xss-con-esapi/" title="Java EE: Seguridad en aplicaciones web (II). Evitando Inyección SQL y XSS con ESAPI">Java EE: Seguridad en aplicaciones web (II). Evitando Inyección SQL y XSS con ESAPI</a></li><li><a href="http://blog.jdiezfoto.es/informatica/ejemplo-javaee-una-tienda-online/" title="Ejemplo Java EE: Una tienda Online">Ejemplo Java EE: Una tienda Online</a></li><li><a href="http://blog.jdiezfoto.es/informatica/presentacion-sobre-seguridad-en-aplicaciones-web/" title="Presentación sobre seguridad en aplicaciones web">Presentación sobre seguridad en aplicaciones web</a></li><li><a href="http://blog.jdiezfoto.es/informatica/jrebel-stop-redeploying/" title="JRebel: Stop Redeploying">JRebel: Stop Redeploying</a></li><li><a href="http://blog.jdiezfoto.es/informatica/vanadium-validacion-de-formularios-con-jquery/" title="Vanadium: Validación de formularios con JQuery">Vanadium: Validación de formularios con JQuery</a></li><li><a href="http://blog.jdiezfoto.es/informatica/tienda-online-java-ee-solucionada-validacion-ajax-en-formulario-de-registro/" title="Tienda Online Java EE: Solucionada validación ajax en formulario de registro">Tienda Online Java EE: Solucionada validación ajax en formulario de registro</a></li><li><a href="http://blog.jdiezfoto.es/informatica/tutorial-ant-uso-con-librerias-externas-y-generadores-jflex-y-cup/" title="Tutorial ANT: Uso con librerías externas y generadores JFlex y CUP">Tutorial ANT: Uso con librerías externas y generadores JFlex y CUP</a></li></ul><p><p>© 2009-2011 Juan Díez-Yanguas Barber </p></p>]]></content:encoded>
			<wfw:commentRss>http://blog.jdiezfoto.es/informatica/java-ee-seguridad-en-aplicaciones-web-i/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Java EE 6: Subida de imágenes al servidor (Servlet 3.0)</title>
		<link>http://blog.jdiezfoto.es/informatica/java-ee-6-subida-de-imagenes-al-servidor-servlet-3-0/</link>
		<comments>http://blog.jdiezfoto.es/informatica/java-ee-6-subida-de-imagenes-al-servidor-servlet-3-0/#comments</comments>
		<pubDate>Wed, 12 Oct 2011 09:12:12 +0000</pubDate>
		<dc:creator>Juan</dc:creator>
				<category><![CDATA[Informática]]></category>
		<category><![CDATA[Java]]></category>

		<guid isPermaLink="false">http://blog.jdiezfoto.es/?p=1317</guid>
		<description><![CDATA[<p>Vamos a ir poco a poco centrándonos en algunas partes concretas del proyecto que presente de la tienda online y así veremos en detalle determinadas partes. Hoy nos vamos a centrar en ofrecer la posibilidad de que el cliente de nuestra web pueda subir imágenes a nuestro servidor web de una manera muy sencilla Antes <a href='http://blog.jdiezfoto.es/informatica/java-ee-6-subida-de-imagenes-al-servidor-servlet-3-0/' class='excerpt-more'>[...]</a></p><p><p>© 2009-2011 Juan Díez-Yanguas Barber </p></p>]]></description>
			<content:encoded><![CDATA[<p style="text-align: center;"><a href="http://blog.jdiezfoto.es/wp-content/uploads/2011/10/UploadImagenes.jpg" rel="lightbox[1317]"><img class="aligncenter size-full wp-image-1421" title="UploadImagenes" src="http://blog.jdiezfoto.es/wp-content/uploads/2011/10/UploadImagenes.jpg" alt="" width="455" height="651" /></a></p>
<p>Vamos a ir poco a poco centrándonos en algunas partes concretas del proyecto que presente de la <a href="http://blog.jdiezfoto.es/informatica/ejemplo-javaee-una-tienda-online/" target="_blank">tienda online</a> y así veremos en detalle determinadas partes. Hoy nos vamos a centrar en ofrecer la posibilidad de que el cliente de nuestra web pueda subir imágenes a nuestro servidor web de una manera muy sencilla</p>
<p><span id="more-1317"></span>Antes de la especificación 3.0 de los Servlets esta tarea se tenía que  hacer usando las librerías de Apache Commons y se convertía en una tarea más larga y menos clara; desde la nueva especificación no es necesario usar ninguna librería externa dado que nos da esta posibilidad de serie y de una manera muy sencilla. Pues bien, comencemos.</p>
<p><span style="font-size: medium;"><strong>El formulario</strong></span></p>
<p>Lo primero que hay que hacer es una pequeña modificación en el formulario donde se quiera subir la imagen, puesto que ahora los datos no se van a enviar en modo texto sino como un flujo binario, y teniendo en cuenta esto último el verbo HTTP usado será POST y nunca GET; de manera que la cabecera de nuestro formulario tendra una forma como la que os muestro.</p>
<pre class="brush: html; gutter: true; first-line: 1; highlight: [1]">&lt;form name="pruebaImagenes" method="post" action="/admin/pruebaimg" enctype="multipart/form-data" &gt;

&lt;/form&gt;</pre>
<p>Una vez que ya tenemos la estructura del formulario HTML, ya podemos añadir los campos que queramos al formulario al igual que lo hacemos normalmente, sabiendo que el campo para seleccionar la imagen sera de tipo <em>file</em>. Una vez hecho nos quedaría algo como lo que sigue.</p>
<pre class="brush: html; gutter: true; first-line: 1; highlight: [5]">&lt;form name="pruebaImagenes" method="post" action="/admin/pruebaimg" enctype="multipart/form-data" &gt;
            &lt;b&gt;Nombre&lt;/b&gt; &lt;br /&gt;
            &lt;input type="text" name="name" /&gt;&lt;br /&gt;&lt;br /&gt;
            &lt;b&gt;Escoja una foto de producto&lt;/b&gt; (Opcional)&lt;br /&gt;
            &lt;input type="file" name="foto" /&gt;&lt;br /&gt;&lt;br /&gt;
            &lt;b&gt;Detalles&lt;/b&gt; &lt;br /&gt;
            Puede usar etiquetas html (si usa etiquetas invalidas sera bloqueado)&lt;br /&gt;
            &lt;textarea name="detail"&gt;&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;
            &lt;input type="submit" name="send" value="Enviar datos" /&gt;
&lt;/form&gt;</pre>
<p><span style="font-size: medium;"><strong>Procesando el formulario</strong></span></p>
<p>Una vez que ya tenemos el formulario HTML preparado ya estaríamos en condiciones de pasar a la parte de servidor para procesar este formulario que hemos creado; es decir, crear el Servlet encargado de procesar este formulario; que veremos que se procesa de una forma algo distinta a como estamos acostumbrados; principalmente debido a que ahora no hemos recibido texto sino un flujo de datos y de ahí tendremos que obtener el texto normal y la fotografía. En el formulario he puesto tres tipos de campos para que veamos como procesar cada uno de ellos (texto, archivo, textarea).</p>
<p>En primer lugar el Servlet encargado de procesar el formulario deberá llevar la anotación @MultipartConfig. Y ahora puede haber varias preguntas clave.</p>
<ul>
<li><strong>¿Cómo se si se ha enviado la imagen o no?</strong> (el usuario pudo no poner la imagen). Sencillo, si el Part (nombre que se le da a un campo en un formulario de este tipo) ocupa cero bits.</li>
<li><strong>¿Cómo se si el archivo que se ha seleccionado es una imagen?</strong> Hay un método para saber el tipo de archivo subido. Si contiene la cadena <em>image</em> sabremos que es una imagen (image/jpeg, etc&#8230;)</li>
<li><strong>¿Cómo guardamos la imagen en disco?</strong> Tendremos que obtener el InputStream del Part.</li>
<li><strong>¿Cómo obtenemos los campos que son de tipo texto, ahora no recibo texto?</strong> Ahora veremos que hay una manera sencilla de hacerlo. Os enseñaré los métodos de la clase estática Tools.</li>
</ul>
<p>Ahora os muestro el código del Servlet completo, he puesto algunos comentarios en el mismo. Está basado en uno de los Servlets de tienda online, he quitado bastante código para mostrar prácticamente solo lo referente al tema que nos concierne ahora en concreto, obviamente entendiendo lo fundamental podemos modificarlo para que cumpla con la función que cada uno desee. En el código veremos que se resaltan las líneas fundamentales que responden a cada una de las preguntas que he planteado en el párrafo anterior. Por supuesto el Servlet estará dado de alta en el descriptor de despliegue y atendiendo peticiones en la ruta a la que se envía el formulario HTML.</p>
<pre class="brush: java; gutter: true; first-line: 1; highlight: [15,29,30,33,35,36,45,47]">import control.Tools;
import java.io.IOException;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @author Juan Díez-Yanguas Barber
 */

//Anotación necesaria para procesar formulario
@MultipartConfig
public class AddServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
				response.sendError(404);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        if (validateForm(request)) {
				//Extraemos el texto del formulario
                String nombre = Tools.getcontentPartText(request.getPart("name"));
                String detalles = Tools.getContentTextArea(request.getPart("detail"));                               

				//Comprobamos si el formulario contiene o no la imagen (usamos el tamaño para comprobar si existe el campo o no)
                if (request.getPart("foto").getSize() &gt; 0) {
					//Nos aseguramos que el archivo es una imagen y que no excece de unos 8mb
                    if (request.getPart("foto").getContentType().contains("image") == false ||
                            request.getPart("foto").getSize() &gt; 8388608) {
						// TIPO DE ARCHIVO NO VALIDO
                        request.setAttribute("resultados", "Archivo no válido");
                        Tools.anadirMensaje(request, "Solo se admiten archivos de tipo imagen");
                        Tools.anadirMensaje(request, "El tamaño máximo de archivo son 8 Mb");
                        request.getRequestDispatcher("/admin/add.jsp").forward(request, response);
                        return;
                    }else{
						//Obtenemos la ruta absoluta del sistema donde queremos guardar la imagen
                        String fileName = this.getServletContext().getRealPath("/images/products/imagen");
						//Guardamos la imagen en disco con la ruta que hemos obtenido en el paso anterior
                        boolean ok = Tools.guardarImagenDeProdructoEnElSistemaDeFicheros(request.getPart("foto").getInputStream(), fileName);
                        if (ok == false){
                            request.setAttribute("resultados", "Fallo al guardar archivo");
                            Tools.anadirMensaje(request, "Ocurrio un error guardando la imagen");
                            request.getRequestDispatcher("/admin/add.jsp").forward(request, response);
                            return;
                        }
                    }
                }
				//TODO CORRECTO SE REDIRIGE A UNA PAGINA DE VISUALIZACIÓN
				Producto prod = new Producto(nombre, detalles);
				request.getSession().setAttribute("productoEnCursoAdd", prod);
				request.setAttribute("operation", "add");
                RequestDispatcher previsualizacion = request.getRequestDispatcher("/WEB-INF/admin/view.jsp");
                previsualizacion.forward(request, response);
        } else {
            request.setAttribute("resultados", "Formulario no válido");
            Tools.anadirMensaje(request, "El formulario recibido no tiene los campos esperados");
            request.getRequestDispatcher("/admin/addproduct.jsp").forward(request, response);
        }
    }

	//Método para validar que el formulario contiene los parámetros correctos
    private boolean validateForm(HttpServletRequest request) throws IOException, ServletException {
        if (request.getParts().size() &gt;= 4 &amp;&amp; request.getPart("name") != null &amp;&amp;
                request.getPart("detail") != null &amp;&amp; request.getPart("send") != null) {
            return true;
        }
        return false;
    }

    @Override
    public String getServletInfo (){
        return "Servlet para añadir productos al catálogo";
    }
}</pre>
<p>Resumiendo, lo primero que hace el servlet es comprobar que se reciben los parámetros correctos y no menos, si la validación ha sido correcta se obtienen los campos de texto como veremos ahora. Posteriormente comprobamos si hay archivo o no, y en caso de que lo haya comprobamos que es una imagen y que el tamaño no exceda de 8 Mb, posteriormente se guarda en disco el archivo. Si quereis obtener más información sobre el archivo os animo a que investigueis los métodos del objeto Part. Es enviado un error 404 para una petición GET que llegue a este servlet debido a que no tendría porque accederse por dicho verbo HTTP (no hay ninguna razón para hacerlo) y podríamos evitarnos así posibles problemas, evitamos que se &#8220;hagan experimentos&#8221; con nuestra aplicación web.</p>
<p>Los atributos que yo añado a la petición son usados para dar el mensaje correspondiente en la jsp a la que se redirige, por lo tanto vosotros hacer caso solo al texto de los mensajes.</p>
<p>Y ahora nos falta ya por concretar como obtener los campos de texto y como guardar la imagen en disco que tal como aparece en el Servlet aparece simplificado al aparecer en una única línea, pero claro, hay que ver lo que hace esa línea.</p>
<p>Para el caso del texto veremos que podemos obtener un InputStream del Part del formulario y podemos leerlo por ejemplo con la clase Scanner de Java. La única diferencia entre obtener el texto de un campo de texto y un textarea será que tenemos que mantener los saltos de línea para el segundo como veremos ahora. Mientras que en un campo de texto solo habrá una línea. Otro apunte importante sería especificar la codificación para evitar errores con caracteres como tildes, eñes o similares. Por último decir que observeis como se abren y se cierran los objetos de tipo Scanner asegurándonos de que se cierren siempre ocurra o error o no.</p>
<pre class="brush: java; gutter: true; first-line: 1; highlight: [5,16,25,35]">public static String getcontentPartText(Part input) {
		Scanner sc = null;
		String content = null;
        try {
            sc = new Scanner(input.getInputStream(), "UTF-8");
            if (sc.hasNext()) {
                content = sc.nextLine();
            } else {
                content = "";
            }
            return content;
        } catch (IOException ex) {
            Logger.getLogger(Tools.class.getName()).log(Level.SEVERE, ex.getMessage());
			content = null;
        }finally{
			sc.close();
		}
		return content;
    }

    public static String getContentTextArea(Part input) {
		StringBuilder sb = null;
		Scanner sc = null;
        try {
            sc = new Scanner(input.getInputStream(), "UTF-8");
            sb = new StringBuilder("");
            while (sc.hasNext()) {
                sb.append(sc.nextLine());
                sb.append("\n");
            }
        } catch (IOException ex) {
            Logger.getLogger(Tools.class.getName()).log(Level.SEVERE, ex.getMessage());
            sb = null;
        }finally{
			sc.close();
		}
		if (sb == null){
			return null
		}else{
			return sb.toString();
		}
    }</pre>
<p>Bueno, y ahora ya solo nos faltaría ver como guardar la imagen en disco, como hemos dicho obteniendo el InputStream del Part del formulario (que ya lo obtuvimos en el Servlet y se lo pasamos ahora a este método estático) y también asegurándonos de cerrar los flujos de datos en todos los casos de error y de éxito.</p>
<pre class="brush: java; gutter: true; first-line: 1">public static boolean guardarImagenDeProdructoEnElSistemaDeFicheros(InputStream input, String fileName)
            throws ServletException {
        FileOutputStream output = null;
        boolean ok = false;
        try {
            output = new FileOutputStream(fileName);
            int leido = 0;
            leido = input.read();
            while (leido != -1) {
                output.write(leido);
                leido = input.read();
            }
        } catch (FileNotFoundException ex) {
            Logger.getLogger(Tools.class.getName()).log(Level.SEVERE, ex.getMessage());
        } catch (IOException ex) {
            Logger.getLogger(Tools.class.getName()).log(Level.SEVERE, ex.getMessage());
        } finally {
            try {
                output.flush();
                output.close();
                input.close();
                ok = true;
            } catch (IOException ex) {
                Logger.getLogger(Tools.class.getName()).log(Level.SEVERE, "Error cerrando flujo de salida", ex);
            }
        }
        return ok;
    }</pre>
<p>Hasta aquí creo que no se me queda ningún aspecto por cubrir, únicamente añadir alguna anotación. Comentar que sería interesante para administrar las imágenes guardar sus nombres en una base de datos haciéndolas corresponder con productos por ejemplo en el caso de una tienda. Y aspectos a corregir de mi modo de hacerlo en el proyecto de la tienda sería guardar las imágenes con extensión, puede ser que no todos los navegadores muestren la imagen correctamente, también sería interesante guardar las imágenes con nombres normales y no con códigos, esto último más que nada para el SEO (Search Engine Optimization), debido a que con nombres normales las imagenes se indexarán mejor en los buscadores.</p>
<p>Ahora ya si que he dicho todo lo que tenía que decir y se han cubierto todos los aspectos sobre el tema. Espero que os sea de utilidad esta guía y como siempre digo estoy abierto a dudas sugerencias o lo que os haga falta.</p>
<h4  class="related_post_title">También te puede interesar:</h4><ul class="related_post"><li><a href="http://blog.jdiezfoto.es/informatica/jrebel-stop-redeploying/" title="JRebel: Stop Redeploying">JRebel: Stop Redeploying</a></li><li><a href="http://blog.jdiezfoto.es/informatica/vanadium-validacion-de-formularios-con-jquery/" title="Vanadium: Validación de formularios con JQuery">Vanadium: Validación de formularios con JQuery</a></li><li><a href="http://blog.jdiezfoto.es/informatica/tienda-online-java-ee-solucionada-validacion-ajax-en-formulario-de-registro/" title="Tienda Online Java EE: Solucionada validación ajax en formulario de registro">Tienda Online Java EE: Solucionada validación ajax en formulario de registro</a></li><li><a href="http://blog.jdiezfoto.es/informatica/java-ee-seguridad-en-aplicaciones-web-ii-evitando-inyeccion-sql-y-xss-con-esapi/" title="Java EE: Seguridad en aplicaciones web (II). Evitando Inyección SQL y XSS con ESAPI">Java EE: Seguridad en aplicaciones web (II). Evitando Inyección SQL y XSS con ESAPI</a></li><li><a href="http://blog.jdiezfoto.es/informatica/tutorial-ant-uso-con-librerias-externas-y-generadores-jflex-y-cup/" title="Tutorial ANT: Uso con librerías externas y generadores JFlex y CUP">Tutorial ANT: Uso con librerías externas y generadores JFlex y CUP</a></li><li><a href="http://blog.jdiezfoto.es/informatica/java-ee-seguridad-en-aplicaciones-web-i/" title="Java EE: Seguridad en aplicaciones web (I)">Java EE: Seguridad en aplicaciones web (I)</a></li><li><a href="http://blog.jdiezfoto.es/informatica/ejemplo-javaee-una-tienda-online/" title="Ejemplo Java EE: Una tienda Online">Ejemplo Java EE: Una tienda Online</a></li></ul><p><p>© 2009-2011 Juan Díez-Yanguas Barber </p></p>]]></content:encoded>
			<wfw:commentRss>http://blog.jdiezfoto.es/informatica/java-ee-6-subida-de-imagenes-al-servidor-servlet-3-0/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Fallece Steve Jobs</title>
		<link>http://blog.jdiezfoto.es/informatica/fallece-steve-jobs/</link>
		<comments>http://blog.jdiezfoto.es/informatica/fallece-steve-jobs/#comments</comments>
		<pubDate>Thu, 06 Oct 2011 10:01:21 +0000</pubDate>
		<dc:creator>Juan</dc:creator>
				<category><![CDATA[Informática]]></category>

		<guid isPermaLink="false">http://blog.jdiezfoto.es/?p=1276</guid>
		<description><![CDATA[<p>Hoy según me he levantado por la mañana me he llevado una sorpresa en mi recorrido habitual de noticias por la web. Ha fallecido Steve Jobs esta noche. Una desagradable sorpresa sin duda alguna, el mundo ha perdido una gran persona. Yo personalmente llevo ya un año manejando un MacBookPro y desde entonces estoy más <a href='http://blog.jdiezfoto.es/informatica/fallece-steve-jobs/' class='excerpt-more'>[...]</a></p><p><p>© 2009-2011 Juan Díez-Yanguas Barber </p></p>]]></description>
			<content:encoded><![CDATA[<p style="text-align: center;"><a href="http://blog.jdiezfoto.es/wp-content/uploads/2011/10/stevejobs.jpg" rel="lightbox[1276]"><img class="aligncenter size-full wp-image-1277" title="stevejobs" src="http://blog.jdiezfoto.es/wp-content/uploads/2011/10/stevejobs.jpg" alt="" width="542" height="380" /></a></p>
<p style="text-align: left;">Hoy según me he levantado por la mañana me he llevado una sorpresa en mi recorrido habitual de noticias por la web. Ha fallecido Steve Jobs esta noche. Una desagradable sorpresa sin duda alguna, el mundo ha perdido una gran persona.</p>
<p style="text-align: left;">Yo personalmente llevo ya un año manejando un MacBookPro y desde entonces estoy más pendiente de las noticias del mundo apple. Steve Jobs sin duda alguna fue un gran visionario y es el responsable de que hoy hagamos muchas cosas de manera totalmente distinta a como las solíamos hacer. Ha sido un gran emprendedor.</p>
<p style="text-align: left;">Desde aquí mi más sincero pésame por la pérdida de una gran persona y visionario como dice su sucesor en el cargo <strong>Tim Cook</strong>.</p>
<p style="text-align: left;"><cite title="Steve Jobs 2005 (Stanford)">“Si vives cada día como si fuera el último, algún día acertarás&#8230; Cada día me miro al espejo como si fuera el último&#8221;</cite><strong> Steve Jobs 2005 (Stanford)</strong></p>
<p style="text-align: left;">En la <a href="http://www.apple.com/es/stevejobs/" target="_blank">página de la compañía</a> le rinden homenaje.</p>
<h4  class="related_post_title">Artículos más comentados</h4><ul class="related_post"><li><a href="http://blog.jdiezfoto.es/informatica/ejemplo-javaee-una-tienda-online/" title="Ejemplo Java EE: Una tienda Online">Ejemplo Java EE: Una tienda Online</a></li><li><a href="http://blog.jdiezfoto.es/santander/fuegos-artificiales-semana-grande-santander-2010/" title="Fuegos artificiales Semana Grande Santander 2010">Fuegos artificiales Semana Grande Santander 2010</a></li><li><a href="http://blog.jdiezfoto.es/santander/los-reflejos-del-sol/" title="Los reflejos del sol">Los reflejos del sol</a></li><li><a href="http://blog.jdiezfoto.es/fotografia/mezquita-de-cordoba/" title="Mezquita de Córdoba">Mezquita de Córdoba</a></li><li><a href="http://blog.jdiezfoto.es/santander/llovera-o-no-llovera/" title="Lloverá o no lloverá">Lloverá o no lloverá</a></li><li><a href="http://blog.jdiezfoto.es/santander/playa-de-arnia-como-en-el-caribe/" title="Playa de Arnia: Como en el Caribe">Playa de Arnia: Como en el Caribe</a></li><li><a href="http://blog.jdiezfoto.es/general/adaptarse-o-morir/" title="Los tiempos cambian">Los tiempos cambian</a></li></ul><p><p>© 2009-2011 Juan Díez-Yanguas Barber </p></p>]]></content:encoded>
			<wfw:commentRss>http://blog.jdiezfoto.es/informatica/fallece-steve-jobs/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Ejemplo Java EE: Una tienda Online</title>
		<link>http://blog.jdiezfoto.es/informatica/ejemplo-javaee-una-tienda-online/</link>
		<comments>http://blog.jdiezfoto.es/informatica/ejemplo-javaee-una-tienda-online/#comments</comments>
		<pubDate>Wed, 21 Sep 2011 21:22:30 +0000</pubDate>
		<dc:creator>Juan</dc:creator>
				<category><![CDATA[Informática]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[seguridad]]></category>
		<category><![CDATA[sql]]></category>

		<guid isPermaLink="false">http://blog.jdiezfoto.es/?p=909</guid>
		<description><![CDATA[<p>Un tienda online desarrollada en Java EE como ejemplo de aplicación web.
Como secularizar aplicaciones web usando librerías (ESAPI y Antisamy de OWASP)
Como hacer upload de imágenes con servlet 3.0
Como enviar emails usando JavaMail
Como configurar un pool de conexiones con GlassFish 3.1
Como generar gráficos usando JFreeChart</p><p><p>© 2009-2011 Juan Díez-Yanguas Barber </p></p>]]></description>
			<content:encoded><![CDATA[<p style="text-align: center;"><a href="http://blog.jdiezfoto.es/wp-content/uploads/2011/08/TiendaOnline.jpg" rel="lightbox[909]"><img class="size-full wp-image-894 aligncenter" title="TiendaOnline" src="http://blog.jdiezfoto.es/wp-content/uploads/2011/08/TiendaOnline.jpg" alt="" width="667" height="443" /></a></p>
<p>Continuando con la <a href="http://blog.jdiezfoto.es/informatica/presentacion-sobre-seguridad-en-aplicaciones-web/">presentación de seguridad en aplicaciones web</a>, aplicado especialmente a Java EE voy a presentar un proyecto que he llevado a cabo este año, un proyecto que se podría acercar bastante a un ejemplo real con Java EE. Una tienda Online.</p>
<p>El proyecto comenzó siendo una asignatura de la universidad, pero conforme fue avanzando me fui involucrando más en ello y fue adquiriendo unas dimensiones que fácilmente acercarían a la aplicación a algo cada vez más orientado a algo real.</p>
<p>Al acabar el curso el profesor de la asignatura, Abraham Otero Quintana me propuso perfeccionar el proyecto con la intención de que fuera útil a mucha más gente, que fuera un ejemplo más avanzado de lo que se suele encontrar en los manuales.</p>
<p><span id="more-909"></span><span style="font-size: large;"><strong>La aplicación</strong></span></p>
<p>El proyecto consiste en una aplicación web Java EE que cumple con las funciones de una tienda online. Consiste en una web en la que los usuarios pueden adquirir una serie de productos y posteriormente realizarán el pago (no se ha implementado ninguna pasarela de pago). Los usuarios de la tienda podrán ser usuarios sin registrar o se podrán registrar en la aplicación, lo que les evitará tener que rellenar sus datos; a la vez que les permitirá dejar comentarios sobre los productos.</p>
<p>Como cualquier aplicación del estilo que se precie dispone de una zona de administración únicamente accesible a usuarios con derechos de administración. En dicha zona se podrá gestionar los productos en venta, los usuarios de la aplicación registrados y también consultar el historial de ventas, con el que se generan una serie de gráficas estadísticas sobre las ventas; por último será posible gestionar los comentarios de los productos. Las características están más detalladas en la documentación.</p>
<p><span style="font-size: large;"><strong>En detalle</strong></span></p>
<p>La aplicación basa su persistencia en el patrón DAO, por lo que es posible implementar varios métodos de persistencia. Por defecto se han implementado la persistencia contra bases de datos (<a href="http://www.mysql.com/" target="_blank">MySQL</a>) y persistencia contra ficheros serializados en disco.</p>
<p>Durante el desarrollo de la aplicación se ha prestado especial atención a varios aspectos: la seguridad, la concurrencia y finalmente un especial cuidado en la detección de fallos y errores en el funcionamiento del sistema.</p>
<p>En el aspecto de la seguridad nos encontraremos con que toda información enviada por el usuario es validada mediante una librería de seguridad (<a href="https://www.owasp.org/index.php/Category:OWASP_Enterprise_Security_API" target="_blank">ESAPI</a>), observaremos también que todo el sistema de URLs está preparado para que solo sea posible acceder a las páginas de la manera que se espera y no de otra manera. Encontraremos más información sobre las medidas tomadas en la documentación del proyecto.</p>
<p>En lo referente a la concurrencia se han hecho las clases encargadas de la persistencia siguiendo el patrón de diseño <a href="http://es.wikipedia.org/wiki/Singleton" target="_blank">Singleton</a> para que no sea posible tener más de una instancia de esa clase. En el caso de la persistencia contra ficheros se han tomado las medidas necesarias para asegurar que los archivos no sean corrompidos realizando escrituras simultáneas; así como en el caso de la persistencia contra bases de datos se ha usado un nivel de aislamiento adecuado para evitar la lectura de datos confirmados (READ COMMITED). Es de especial interés en lo que a concurrencia se refiere la manera en la que se hace la compra de un carrito y se disminuyen las unidades en el almacén.</p>
<p><span style="font-size: large;"><strong>Recursos</strong></span></p>
<p>He decidido publicar el código fuente completo en un repositorio de google code, también dejo las sentencias SQL necesarias para crear la base de datos. He realizado también un escrito como documentación en el que se puede observar el funcionamiento más en detalle de la aplicación. Por último he realizado un videotutorial en el que se explica desde cero como montar la aplicación y todo lo necesario para que esta funcione.</p>
<ul>
<li><a href="http://blog.jdiezfoto.es/wp-content/uploads/2011/08/OnlineShop.pdf" target="_blank">Documentación</a></li>
<li><a href="http://code.google.com/p/tiendaonlinelpijdyb/" target="_blank">Repositorio Google Code</a></li>
<li><a href="http://blog.jdiezfoto.es/wp-content/uploads/2011/08/ExportModelo.sql" target="_blank">Configuración de las bases de datos</a></li>
<li><a href="http://vimeo.com/user8585587/tienda-online-javaee" target="_blank">Videotutorial en vimeo</a>. <a class="lbpModal" title="Videotutorial Tienda Online" href="http://player.vimeo.com/video/29328312">Abrir reproductor</a></li>
</ul>
<p>Espero que os haya gustado y os haya ayudado este ejemplo de programación con Java EE. La publicación es totalmente desinteresada y con fines didácticos; si alguien estuviese interesado en utilizarlo para algún otro fin o seguir trabajando en ello me gustaría que me lo comunicase y se podrían publicar las mejoras.</p>
<p>Estoy abierto a cualquier duda al respecto ya sea con un comentario, contactando conmigo mediante el <a href="http://www.jdiezfoto.es/contacto.html" target="_blank">formulario de contacto</a> o mediante los medios que se indican en la documentación o en <a href="https://twitter.com/#!/jdiezfoto" target="_blank">Twitter</a>.</p>
<p><strong>Actualización:</strong> El artículo ha sido publicado en <a href="http://www.javahispano.org/portada/2011/10/23/ejemplo-de-aplicacion-java-ee-una-tienda-online.html" target="_blank">JavaHispano</a> por Abraham Otero. Creo que es interesante ver los comentarios que se han publicado allí, entre otras cosas por anotaciones interesantes que se han hecho y que se hagan.</p>
<h4  class="related_post_title">También te puede interesar:</h4><ul class="related_post"><li><a href="http://blog.jdiezfoto.es/informatica/java-ee-seguridad-en-aplicaciones-web-ii-evitando-inyeccion-sql-y-xss-con-esapi/" title="Java EE: Seguridad en aplicaciones web (II). Evitando Inyección SQL y XSS con ESAPI">Java EE: Seguridad en aplicaciones web (II). Evitando Inyección SQL y XSS con ESAPI</a></li><li><a href="http://blog.jdiezfoto.es/informatica/java-ee-seguridad-en-aplicaciones-web-i/" title="Java EE: Seguridad en aplicaciones web (I)">Java EE: Seguridad en aplicaciones web (I)</a></li><li><a href="http://blog.jdiezfoto.es/informatica/presentacion-sobre-seguridad-en-aplicaciones-web/" title="Presentación sobre seguridad en aplicaciones web">Presentación sobre seguridad en aplicaciones web</a></li><li><a href="http://blog.jdiezfoto.es/informatica/jrebel-stop-redeploying/" title="JRebel: Stop Redeploying">JRebel: Stop Redeploying</a></li><li><a href="http://blog.jdiezfoto.es/informatica/vanadium-validacion-de-formularios-con-jquery/" title="Vanadium: Validación de formularios con JQuery">Vanadium: Validación de formularios con JQuery</a></li><li><a href="http://blog.jdiezfoto.es/informatica/tienda-online-java-ee-solucionada-validacion-ajax-en-formulario-de-registro/" title="Tienda Online Java EE: Solucionada validación ajax en formulario de registro">Tienda Online Java EE: Solucionada validación ajax en formulario de registro</a></li><li><a href="http://blog.jdiezfoto.es/informatica/tutorial-ant-uso-con-librerias-externas-y-generadores-jflex-y-cup/" title="Tutorial ANT: Uso con librerías externas y generadores JFlex y CUP">Tutorial ANT: Uso con librerías externas y generadores JFlex y CUP</a></li></ul><p><p>© 2009-2011 Juan Díez-Yanguas Barber </p></p>]]></content:encoded>
			<wfw:commentRss>http://blog.jdiezfoto.es/informatica/ejemplo-javaee-una-tienda-online/feed/</wfw:commentRss>
		<slash:comments>39</slash:comments>
		</item>
	</channel>
</rss>

<!-- Dynamic page generated in 1.423 seconds. -->
<!-- Cached page generated by WP-Super-Cache on 2012-02-22 23:36:32 -->
<!-- Compression = gzip -->
