<?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>Jdiezfoto &#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>Mon, 14 May 2012 10:54:36 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
<xhtml:meta xmlns:xhtml="http://www.w3.org/1999/xhtml" name="robots" content="noindex" />
		<item>
		<title>Internet, ¿Qué es y como funciona?</title>
		<link>http://blog.jdiezfoto.es/informatica/internet-que-es-y-como-funciona/</link>
		<comments>http://blog.jdiezfoto.es/informatica/internet-que-es-y-como-funciona/#comments</comments>
		<pubDate>Thu, 12 Apr 2012 11:07:01 +0000</pubDate>
		<dc:creator>Juan</dc:creator>
				<category><![CDATA[Informática]]></category>
		<category><![CDATA[Internet]]></category>
		<category><![CDATA[Redes]]></category>

		<guid isPermaLink="false">http://blog.jdiezfoto.es/?p=2263</guid>
		<description><![CDATA[<p>Seguramente ha llamado la atención el título de la entrada, no es una pregunta que se haga uno muy a menudo, lo usamos, lo conocemos y con eso nos vale. Pero, realmente sabemos lo que estamos usando y que hay detrás de todo ello. Pues eso es justamente lo que pretendo con esta entrada, concretar <a href='http://blog.jdiezfoto.es/informatica/internet-que-es-y-como-funciona/' class='excerpt-more'>[...]</a></p><p><p>© 2009-2012 Juan Díez-Yanguas Barber </p></p>]]></description>
			<content:encoded><![CDATA[<div id="attachment_2334" class="wp-caption aligncenter" style="width: 699px"><img class="wp-image-2334" title="InternetMap" src="http://blog.jdiezfoto.es/wp-content/uploads/2012/04/InternetMap-1024x1024.jpg" alt="" width="689" height="689" /><p class="wp-caption-text">Imagen obtenida de Wikipedia.org</p></div>
<p>Seguramente ha llamado la atención el título de la entrada, no es una pregunta que se haga uno muy a menudo, lo usamos, lo conocemos y con eso nos vale.</p>
<p>Pero, realmente sabemos lo que estamos usando y que hay detrás de todo ello. Pues eso es justamente lo que pretendo con esta entrada, concretar un poco los conocimientos que tenemos sobre Internet. Todo esto viene de un trabajo que he tenido que hacer en la Universidad y elegí este tema a investigar y preparar una presentación, y después de acabarlo me he dado cuenta de todas las cosas interesantes que he descubierto y quiero compartirlo con vosotros.</p>
<p>No es fácil encontrar un sitio que te diga que es Internet, llegar a una conclusión razonable es un trabajo de <em>&#8220;bucear&#8221;</em> por la red e ir sintetizando y uniendo trozos de la información que se va encontrando. Dicho esto es de suponer que en este artículo serán abordados muchos temas para conocer como está formado Internet; por lo tanto la lectura ha de ser tranquila, y en caso de no entender algo siempre que conozca la respuesta intentaré aclararla <img src='http://blog.jdiezfoto.es/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<p><span id="more-2263"></span>Voy a dividir el artículo principalmente en dos partes fundamentales, <a href="#tecnico">una parte más técnica</a> y otra parte <a href="#general">orientada a todos los públicos</a> con  curiosidades varias sobre la topología de Internet, empresas y finalmente un tema a simple vista sencillo pero muy interesante: los cables submarinos. Y, finalmente lo que haré será dejar a vuestra disposición la presentación que hice como resultado de este trabajo de búsqueda de información.</p>
<p><strong><span style="font-size: xx-large;">1. Introducción</span></strong></p>
<p>Internet tiene sus orígenes en el año 1969 con el nacimiento de <a href="http://es.wikipedia.org/wiki/ARPANET" target="_blank">ARPANET</a> (<em>Advanced Research Projects Agency Networks</em>), una red construida con el fin de interconectar los ordenadores de varias universidades de los EEUU, que posteriormente se convirtió en un proyecto  militar. Si actualmente me pidieran que definiera lo que es Internet con las menos palabras posibles diría que es un conjunto de redes de varias empresas interconectadas; denominando a cada una de esas redes <a href="http://es.wikipedia.org/wiki/Sistema_aut%C3%B3nomo" target="_blank">Sistemas Autónomos</a> (AS &#8211; <em>Autonomous System</em>).</p>
<p>Si queréis conocer más acerca de la historia de Internet han publicado un interesante artículo en <a href="http://www.omicrono.com/2012/04/asi-nacio-internet-de-una-prediccion-revolucionaria-al-universo-digital-que-conocemos/" target="_blank">Omicrono</a> en el que se presenta un vídeo bastante interesante. Lo recomiendo.</p>
<p><a id="tecnico"> </a><br />
<strong><span style="font-size: large;">1.1. Sistema Autónomo</span></strong></p>
<p>Como hemos dicho un Sistema Autónomo es una de las redes de las que hablábamos que compone Internet, pero más formalmente estaríamos hablando de un conjunto de encaminadores y redes que son gestionados por una única empresa. Y, esos encaminadores como resultado de estar todos dentro de un mismo Sistema Autónomo han de intercambiar información de encaminamiento mediante un protocolo común.</p>
<div id="attachment_2331" class="wp-caption alignleft" style="width: 461px"><img class="wp-image-2331" style="text-align: center;" title="SistemasAutonomos" src="http://blog.jdiezfoto.es/wp-content/uploads/2012/04/SistemasAutonomos-1024x700.png" alt="" width="451" height="308" /><p class="wp-caption-text">Comunicaciones y Redes de Computadores - William Stallings</p></div>
<p>Hablando de Protocolos vamos a distinguir entre dos tipos, el usado en el interior de un Sistema Autónomo y el protocolo que sirve de unión entre todos los Sistemas Autónomos.</p>
<p>IRP. <em>Interior Router Protocol</em>: Es el protocolo de encaminamiento usado dentro de un mismo Sistema Autónomo, no ha de ser el mismo en todos los AS.</p>
<p>ERP. <em>Exterior Router Protocol</em>: Este es el protocolo encargado de transmitir información de encaminamiento entre todos los Sistemas Autónomos, este será igual en todo Internet; en la actualidad el protocolo usado para este fin es BGP (<em>Border Gateway Protocol</em>). Este protocolo no necesita conocer el interior de un Sistema Autónomo; en definitiva este protocolo solo necesita saber el AS objetivo y los Sistemas Autónomos que tiene que atravesar para llegar al mismo.</p>
<p><span style="font-size: large;"><strong>1.2.- Algoritmo de Dijkstra</strong></span></p>
<p>Este va a ser un algoritmo que vamos a presentar en la introducción para usarlo posteriormente en la explicación de <a href="http://es.wikipedia.org/wiki/Open_Shortest_Path_First" target="_blank">OSPF</a> (<em>Open Shortest Path First</em>), el protocolo de encaminamiento interior por excelencia. En definitiva, el objetivo de este algoritmo será encontrar los caminos más cortos desde un nodo origen hacia el resto de los nodos.</p>
<p>Si empezamos a vislumbrar el asunto nos damos cuenta de lo bueno que sería que cada encaminador dentro de un Sistema Autónomo conociera el resto de la topología del AS y con ella encontrar los caminos más cortos hacia el resto de los encaminadores con este algoritmo; pues, veremos más adelante que eso es exactamente lo que se hace.</p>
<p>Definamos una serie de aspectos necesarios para explicar el algoritmo.</p>
<ul>
<li>N: Conjunto de nodos de la red</li>
<li>s: Nodo origen</li>
<li>T: Conjunto de nodos incorporados por el algoritmo</li>
<li>w(i, j): Coste desde el nodo i hasta j</li>
<li>L(n): Coste en curso obtenido para el camino de mínimo coste desde el nodo s hasta el nodo n</li>
</ul>
<div id="attachment_2291" class="wp-caption alignright" style="width: 469px"><a href="http://blog.jdiezfoto.es/wp-content/uploads/2012/04/DijkstraEjemplo.png" rel="lightbox[2263]"><img class="wp-image-2291" title="DijkstraEjemplo" src="http://blog.jdiezfoto.es/wp-content/uploads/2012/04/DijkstraEjemplo-1024x755.png" alt="" width="459" height="338" /></a><p class="wp-caption-text">Comunicaciones y Redes de Computadores - William Stallings</p></div>
<p>Una vez que ya hemos definido las variables que necesitamos nos ponemos a ver en que consiste el algoritmo; consta de tres pasos, el primero de ellos de inicialización y los dos siguientes son los que se repetirán iteración tras iteración hasta que se hayan añadido a T todos los nodos de N, que será el momento en el que se han asignado las rutas finales a todos los nodos de la red.</p>
<ol>
<li>Consiste únicamente en añadir el nodo origen al conjunto T y posteriormente anotar el coste de los caminos hacia los nodos alcanzables desde el nodo origen.</li>
<li>Tiene como objetivo la búsqueda del siguiente nodo para añadir al conjunto T, que ha de ser el más cercano al nodo origen (hablando de costes) y que no se haya añadido previamente a T.</li>
<li>En este paso lo que haremos será recalcular el coste desde el nodo origen hacia todos los nodos (que sean alcanzables con los nodos añadidos a T), puesto que al añadirse un nodo a T se ha abierto la posibilidad a más rutas posibles y puede que con menor coste que las que se tenían anteriormente.</li>
</ol>
<p>En la presentación que voy a dejar disponible se puede ver más en detalle el algoritmo junto con un ejemplo como el que podemos ver en la imagen pero realizado paso por paso.</p>
<p><span style="font-size: xx-large;"><strong>2. OSPF (Open Shortest Path First)</strong></span></p>
<p>También llamado como protocolo del camino más corto disponible, como ya se ha dicho es el protocolo de encaminamiento interior por excelencia.</p>
<p>Como ya se ha ido adelantando, el objetivo es hayar los caminos con menor coste a través de la interconexión de redes. Se caracteriza por ser capaz de equilibrar la carga entre varios caminos de igual coste.</p>
<p>Una de las grandes ventajas que tiene es que el coste es totalmente configurable, podemos usar métricas atendiendo al retardo, velocidad de transmisión, costes económicos u otros factores.</p>
<p>Consigue realizar estas tareas gracias a que es capaz de almacenar en su interior un grafo que representa toda la topología de la red y aplicar sobre él el Algoritmo de Dijkstra que ya hemos comentado para obtener los caminos mínimos hacia el resto de los encaminadores o redes del Sistema Autónomo y como resultado de este árbol construye la tabla de encaminamiento de manera totalmente automática.</p>
<p>De nuevo comento que en la presentación que dejo a vuestra disposición al final del artículo podemos encontrar el detalle de la construcción del grafo a partir de la topología de red con las explicaciones necesarias y con el ejemplo correspondiente.</p>
<p><span style="font-size: xx-large;"><strong>3. BGP (Border Gateway Protocol)</strong></span></p>
<p>Entender este protocolo es la clave de la cuestión que hoy nos atañe, entendiendo su objetivo es como realmente nos podemos hacer una idea de como funciona Internet, de como es capaz de llevar nuestros datos de un extremo a otro del mundo y saber exactamente la ruta que ha de seguir para ello; que para mí fue la pregunta clave que me llevó a elegir este tema para el trabajo.</p>
<p>También conocido como <a href="http://es.wikipedia.org/wiki/Border_Gateway_Protocol" target="_blank">Protocolo de Pasarela Frontera</a>. Es el usado para intercambiar información de encaminamiento entre todos los Sistemas Autónomos; con este protocolo nodos de diferentes AS decidirán ser vecinos e intercambiar información de encaminamiento poniendo unos en conocimiento de otros las redes que son alcanzables desde cada uno de ellos y los AS que se han de atravesar para alcanzar dichas redes.</p>
<p>El protocolo se basa principalmente en obtener las rutas hacia cada una de las redes y posteriormente el paso clave, cuando un encaminador obtiene una ruta para un conjunto de redes comparte esa información con sus vecinos de manera que poco a poco se van formando las Bases de Datos de las redes alcanzables y las rutas que se han de seguir en cada uno de los encaminadores de la interconexión de redes que implementen BGP. Imaginando este paso que describo a lo grande, con las dimensiones de Internet es como uno se llega a hacer a la idea de como funciona y como cada uno de los encaminadores saben exactamente lo que han de hacer para transferirse la información entre ellos.</p>
<p style="text-align: center;"><a href="http://blog.jdiezfoto.es/wp-content/uploads/2012/04/BGP1.png" rel="lightbox[2263]"><img class="wp-image-2339 aligncenter" title="BGP1" src="http://blog.jdiezfoto.es/wp-content/uploads/2012/04/BGP1-1024x536.png" alt="" width="626" height="327" /></a></p>
<p style="text-align: center;"><a href="http://blog.jdiezfoto.es/wp-content/uploads/2012/04/BGP2.png" rel="lightbox[2263]"><img class="wp-image-2340 aligncenter" title="BGP2" src="http://blog.jdiezfoto.es/wp-content/uploads/2012/04/BGP2-1024x558.png" alt="" width="626" height="340" /></a></p>
<p>Al igual que ya he comentado en apartados anteriores se puede seguir el tema con más rigurosidad en la presentación que dejo a vuestra disposición en donde se pueden encontrar ejemplos de los casos que propongo junto con el protocolo en detalle con sus tipos de mensajes y operaciones posibles.</p>
<p><a id="general"> </a><br />
<span style="font-size: xx-large;"><strong>4. Punto Neutro</strong></span></p>
<p>A partir de este momento es donde orientamos el artículo de manera totalmente diferente, más orientado a todos los públicos y explicando como se forma Internet, las empresas que lo componen, tipos de acuerdos entre ellas y conceptos importantes como el que vamos a definir ahora.</p>
<p><a href="http://es.wikipedia.org/wiki/Punto_neutro" target="_blank">IXP (<em>Internet Exchange Point</em>)</a> o NAP (<em>Network Access Point</em>). Es una infraestructura física en la que se intercambian tráfico de Internet varios operadores entre sí. La ventaja de ello es hacer una interconexión directa entre ellos en vez de hacerlo a través de las redes de terceros. En definitiva está compuesto por uno o varios conmutadores de los <a href="http://es.wikipedia.org/wiki/Proveedor_de_servicios_de_Internet" target="_blank">ISP (<em>Internet Service Provider</em>)</a> participantes en dicho Punto Neutro.</p>
<div id="attachment_2356" class="wp-caption alignleft" style="width: 490px"><a href="http://blog.jdiezfoto.es/wp-content/uploads/2012/04/ConmutadorFibraOptica_low.jpg" rel="lightbox[2263]"><img class="wp-image-2356" title="ConmutadorFibraOptica_low" src="http://blog.jdiezfoto.es/wp-content/uploads/2012/04/ConmutadorFibraOptica_low.jpg" alt="" width="480" height="320" /></a><p class="wp-caption-text">Conmutador de Fibra Óptica en el Punto Neutro de Amsterdam AMS-IX. Imagen de Wikipedia.org</p></div>
<p>Otra de las ventajas del uso de un Punto Neutro viene dada por cuestiones económicas; el tráfico que atraviesa un IXP no es facturado. Únicamente cuando el IXP lo han de mantener los ISP pagan por la velocidad del puerto que estén usando cada uno, pero en ningún caso pagan por el volumen de tráfico transferido.</p>
<p>En España disponemos de <a href="http://www.espanix.net/" target="_blank">Espanix</a>, el Punto Neutro Español, es el noveno en términos de tamaño del mundo y lo tenemos situado en Madrid en el CPD de Banesto. Como curiosidad comentar que está a disposición del público el <a href="http://mrtg.espanix.net/espanix/espanix.html" target="_blank">volumen de tráfico que atraviesa este IXP</a>. Es probable que pensemos que esto únicamente sirve como dato de curiosidad, pero recientemente he descubierto que su utilidad va mucho más allá; por ejemplo he visto su uso como medio para medir el <a href="http://www.elmundo.es/elmundo/2012/03/29/navegante/1333022930.html" target="_blank">impacto de la reciente Huelga General en Internet</a>.</p>
<p>Por algún otro Punto Neutro podríamos hablar de <a href="http://www.de-cix.net/" target="_blank">DE-CIX</a> situado en Alemania, el que se dice que es el más grande del mundo con un tráfico medio diario de 900 Gbs y 3 Tbs de pico; pueden servir estas cifras para hacernos una idea del volumen de tráfico que puede llegar a atravesar un IXP.</p>
<p>Finalmente nombremos a <a href="http://www.ams-ix.net/" target="_blank">AMS-IX</a>, el Punto Neutro de Amsterdam que se puede ver en la imagen; del que también podemos ver los <a href="http://www.ams-ix.net/connected" target="_blank">participantes</a> y las <a href="http://www.ams-ix.net/statistics/" target="_blank">estadísticas de tráfico</a>.</p>
<p><span style="font-size: xx-large;"><strong>5. Core Router</strong></span></p>
<p>Lo que significa en español <a href="http://en.wikipedia.org/wiki/Core_router" target="_blank">Router de núcleo</a>. Es el concepto usado para denominar a los routers que se usan en el núcleo de Internet; es decir, serán los router usados en el <a href="http://en.wikipedia.org/wiki/Internet_backbone" target="_blank"><em>Internet Backbone</em></a> (espina dorsal de Internet) y en los Puntos Neutros.</p>
<p>Son equipos con soporte para los protocolos enrutamiento usados en Internet como los que ya hemos visto tanto para el interior de un Sistema Autónomo (OSPF) como para la interconexión de estos (BGP) y lógicamente con varias interfaces de gran capacidad para el reenvío de paquetes IP a gran velocidad por cada una de ellas.</p>
<p><span style="font-size: xx-large;"><strong>6. Peering y Tránsito IP</strong></span></p>
<p>En este apartado lo que haremos será ver los tipos de acuerdos que llevan a cabo las operadoras o ISP entre sí.</p>
<p><strong>Tránsito IP:</strong> Acuerdo que permite enviar y recibir tráfico entre operadores que no tienen una conexión directa entre sí. La conexión se hace a través de un tercero al que se le tiene que pagar.</p>
<p><strong>Peering:</strong> Enlace entre dos operadores directamente conectados. El tráfico es originado en uno de ellos y con destino el otro. En este caso al ser un intercambio de tráfico habitualmente el pago es ese mismo intercambio.</p>
<p>Podemos ver un ejemplo en los <a href="http://www.espanix.net/esp/peering.htm" target="_blank">participantes del Punto Neutro de Espanix</a>, en donde podemos encontrar los acuerdos entre los diferentes ISP participantes así com observar que no siempre son conocidos los acuerdos entre operadores al no ser públicos, a lo que hago mención en el siguiente apartado.</p>
<p><span style="font-size: xx-large;"><strong>7. ISP Tier</strong></span></p>
<p>Como se puede esperar en algo tan grande como es Internet deben existir una serie de niveles para lograr la mejor organización posible. No existe una autoridad encargada de definir los niveles que intervienen en Internet, pero aún así se suele distinguir entre tres niveles.</p>
<div id="attachment_2325" class="wp-caption alignleft" style="width: 455px"><a href="http://blog.jdiezfoto.es/wp-content/uploads/2012/04/ISPTier.png" rel="lightbox[2263]"><img class="wp-image-2325" title="ISPTier" src="http://blog.jdiezfoto.es/wp-content/uploads/2012/04/ISPTier-1024x597.png" alt="" width="445" height="259" /></a><p class="wp-caption-text">Imagen obtenida de Wikipedia.org</p></div>
<p><a href="http://en.wikipedia.org/wiki/Tier_1_network" target="_blank"><strong>ISP Tier 1:</strong></a> Se podría definir como el nivel de ISP que puede alcanzar Internet sin llegar a ningún tipo de acuerdo con terceros. A veces no es posible saber si realmente un ISP es de nivel 1 porque no todos los acuerdos entre operadores son públicos, muchas veces los acuerdos entre ellos no son conocidos.</p>
<p>Hay varios ISP de nivel 1, los podemos encontrar en el enlace que he dejado, pero podríamos destacar <a href="http://www.globalcrossing.com/LATAM/sp/Default.aspx" target="_blank">Global Crossing y Level 3</a> (antes dos empresas que actualmente están unidas); normalmente este tipo de empresas no proporcionan demasiada información sobre su red, aunque sí un mapa de la topología de su red; un ejemplo de ello es el que se puede ver en la web de <a href="http://maps.level3.com/" target="_blank">Global Crossing y Level 3</a>. Podemos por ejemplo ver también la <a href="http://www.cogentco.com/es/network/network-map" target="_blank">topología de red de Cogent Communications</a> o la de <a href="http://www.internationalservices.telefonica.com/mapaFlash.html" target="_blank">Telefónica Wholesale Services</a>.</p>
<p><a href="http://en.wikipedia.org/wiki/Tier_2_network" target="_blank"><strong>ISP Tier 2:</strong></a> Son aquellas redes que necesitan de un ISP Tier 1 para alcanzar Internet; se dice que son los clientes de los ISP Tier 1 y estos son los proveedores. Normalmente tienen una cobertura nacional o regional. En el enlace que he proporcionado se puede ver un ejemplo de los mismos junto con los acuerdos conocidos entre ellos; es decir, una lista de los ISP de nivel 2 junto con los ISP de nivel 1 con los que tienen acuerdos de tránsito para alcanzar Internet.</p>
<p><strong>ISP Tier 3:</strong> Una red que únicamente adquiere tránsito IP de otras empresas para alcanzar en Internet.</p>
<p><strong><span style="font-size: xx-large;">8. Topología Abstracta de Internet</span></strong></p>
<p>Con esto me quiero referir a unos curiosos mapas que nos podemos encontrar por Internet cuando buscamos la topología del mismo (como el que podemos encontrar en la cabecera de este artículo). En primer lugar, como se puede esperar después de lo explicado sobre como se forma Internet; no se puede encontrar un mapa de la topología de Internet completo, son muchas empresas las que lo componen y eso imposibilita la elaboración de esta topología, lo que nos podemos encontrar como ya hemos visto es la topología de la red de los diferentes operadores.</p>
<p>Otro caso es el de los mapas abstractos de los que os hablaba que en definitiva son el resultado de varios estudios con el fin de comprender el volumen de Internet; estos resultados se representan en forma de red neuronal que es lo que nosotros vemos cuando buscamos por la Topología de Internet.</p>
<p>Podemos ver un muy buen ejemplo de la <a href="http://www2.research.att.com/~north/news/img/ATT_Labs_InternetMap_0730_10.pdf" target="_blank">topología de Internet en un estudio de ATT Labs</a>. Es un pdf, recomiendo ampliarlo para visualizarlo en detalle.</p>
<p><span style="font-size: x-large;"><strong>9. Cables Submarinos</strong></span></p>
<p>Lo <a href="http://wikitel.info/wiki/Cable_submarino" target="_blank">cables submarinos</a> no dejan de ser un cojunto de fibras ópticas destinadas a su utilización bajo el mar, y por ello son algo distintas de las que podemos ver en cualquier otro sitio.</p>
<p>La fibra óptica es capaz de transmitir la luz con unas ligeras pérdidas; el problema es que se suele decir que la fibra es un producto perfecto e inmejorable, luego es de esperar que si se quiere transmitir luz con una mínima pérdida haya que investigar sobre otras soluciones posibles. Por ejemplo, se está observando un animal de las profundidades llamado <a href="http://www.cibsub.com/bioespecie_es-aphrodita_aculeata-32845" target="_blank">Ratón Marino (<em>Aphrodita aculeata</em>)</a> que, está recubierto por unas fibras que al parecer por su estructura son capaces de transmitir la luz con una mínima pérdida.</p>
<div id="attachment_2321" class="wp-caption aligncenter" style="width: 635px"><img class="wp-image-2321" title="CableSubmarino" src="http://blog.jdiezfoto.es/wp-content/uploads/2012/04/CableSubmarino.png" alt="" width="625" height="221" /><p class="wp-caption-text">Imagen obtenida de Wikitel.info</p></div>
<p>Aún así, se puede afirmar que 12 fibras pueden abastecer las comunicaciones de un País entero (de forma genérica sin tener en cuenta el tamaño del País).</p>
<p>Cuando estamos hablando de los cables submarinos no solo nos preocupa la fibra sino que nos preocupan muchos aspectos más como son la composición y capas de clable; los cables deben de soportar todo tipo de incidencias, como mordeduras de animales, anclas de los barcos, redes de pesca&#8230;</p>
<p>Si os ha gustado el tema de los cables submarinos después de leer el artículo se pueden ver dos interesantes documentales acerca del tema. Uno del <a href="http://www.youtube.com/watch?v=k8pkPvrnlhg" target="_blank">Discovery Channel</a>, y otro del <a href="http://www.youtube.com/results?search_query=internet+submarino" target="_blank">Canal Odisea</a> (buscando &#8220;internet submarino&#8221; en Youtube podemos ver las 4 partes que lo componen).</p>
<p><span style="font-size: large;"><strong>9.1.- Instalación</strong></span></p>
<p>La colocación de los cables sobre el lecho marino es una operación que nos puede parecer simple; pero no es en absoluto una operación trivial, por ello merece la pena una pequeña observación sobre las tareas que se llevan a cabo en la operación.</p>
<div id="attachment_2315" class="wp-caption alignleft" style="width: 471px"><a href="http://blog.jdiezfoto.es/wp-content/uploads/2012/04/InstalacionCableSubmarino.gif" rel="lightbox[2263]"><img class="wp-image-2315" title="InstalacionCableSubmarino" src="http://blog.jdiezfoto.es/wp-content/uploads/2012/04/InstalacionCableSubmarino.gif" alt="" width="461" height="288" /></a><p class="wp-caption-text">Animación obtenida de Wikitel.info</p></div>
<p>En primer lugar lo que se debe de hacer es cargar los cables en los barcos cableros (barcos especiales destinados a este fin); esto es un proceso manual en el que se va enrollando el cable en las gigantescas bobinas de los barcos; y a todo ello hay que sumar la carga de los repetidores (aparatos encargados de repetir la señal cada cierta distancia para evitar su pérdida) cada 50-100 Km de cable, que es otra operación muy delicada.</p>
<p>Una vez que los barcos han sido cargados se pasa a la instalación de los cables, empezando por la estación terminal en tierra, en la que se ha de fijar correctamente el cable para evitar tirones y otros problemas como consecuencia de lo que pase en el mar. Posteriormente, una vez ya en el mar lo que se hace es ir enterrando el cable según se va soltando del barco mediante una pieza especial llamada arado. El barco irá siempre a una velocidad constante independientemente de las condiciones en las que este el mar, de tener una velocidad variable el cable podría partirse por su propio peso al caer del barco; de ahí la extrema delicadeza con la que se han de realizar todas las operaciones.</p>
<p>Como medida de protección en las proximidades de las cosas los buzos se van encargando de cubrir el cable con piezas de acero para evitar en la mayor medida posible los golpes de los anclas de los barcos.</p>
<p><span style="font-size: large;"><strong>9.2. Reparación</strong></span></p>
<p>Pues sí, los cables submarinos tienen que ser reparados a pesar de los medios y esfuerzos que se gastan en la instalación de los mismos; y además, la reparación de estos cables puede costar cientos de miles de euros o incluso millones, es un proceso costoso y complicado.</p>
<p>El proceso en primer lugar para el usuario es transparente, ya que por cada fibra instalada en el lecho marino hay conexiones de apoyo para los casos en los que se producen las roturas y que ello no suponga la suspensión completa de la comunicación.</p>
<p>Los fallos en los cables son detectados desde las estaciones terminales; desde las que es posible detectar el kilómetro exacto en el que se ha producido la rotura del cable. Una vez que se ha detectado se ha de enviar el barco para las reparaciones, una vez que el barco está en las proximidades del cable se envían señales eléctricas desde la estación terminal, las cuales el barco es capaz de detectar.</p>
<p>En las estaciones terminales están situados unos equipos llamados PFE (<em>Power Feer Equipment</em>. Equipo de Alimentación Eléctrica), cuya función consiste en la gestión energética de los cables submarinos (sí, llevan energía eléctrica a parte de luz, los repetidores necesitan alimentación para cumplir su función). Desde estos equipos es desde donde son enviadas las señales eléctricas para que el barco las detecte.</p>
<div id="attachment_2319" class="wp-caption alignright" style="width: 458px"><a href="http://blog.jdiezfoto.es/wp-content/uploads/2012/04/AnimacionReparacionCable.gif" rel="lightbox[2263]"><img class="wp-image-2319" title="AnimacionReparacionCable" src="http://blog.jdiezfoto.es/wp-content/uploads/2012/04/AnimacionReparacionCable.gif" alt="" width="448" height="336" /></a><p class="wp-caption-text">Animación obtenida de Wikitel.info</p></div>
<p>Las señales cumplen una doble función, en primer lugar ayudan al barco a localizar el cable exactamente y también ayudan a detectar el punto exacto de la rotura, ya que donde se corte esa señal será donde se ha producido la rotura del mismo.</p>
<p>Una vez que se ha detectado la rotura lo que se hace es enviar un robot al lecho marino, dicho robot tendrá que desenterrar el cable y subirlo a bordo en donde se tendrá que cortar para después unir los dos extremos. Cuando hablamos de unir los dos extremos no hablamos de unir un hilo de cobre de nuestra casa, estamos hablando de un proceso costoso llevado a cabo por personal cualificado para unir fibras ópticas y en un lugar especial del barco totalmente limpio y sin partículas de polvo. El proceso puede llevar aproximadamente unas 24 h.</p>
<p>Una vez que se ha llevado a cabo la unión se deberá comprobar el funcionamiento correcto del cable y en caso de que la comprobación sea positiva se volverá a dejar de nuevo el cable en el lecho marino.</p>
<hr />
<p>Pues hasta aquí he llegado con mi particular investigación sobre el tema, me parece un tema que es muy interesante y del que sin duda me queda mucho por averiguar; pero lo que no cabe duda es que con este pequeño acercamiento he aprendido muchas cosas y concretado muchas cosas que hasta ahora para mí solo eran suposiciones.</p>
<p>Os dejo también aquí un interesante enlace hacia la web de <a href="http://spanish.akamai.com/enes/html/technology/visualizing_akamai.html" target="_blank">Akamai donde podemos ver  estadísticas variadas del uso de Intenet a nivel mundial</a>.</p>
<p>Como lo prometido es deuda, os dejo la presentación que llevo prometiendo todo el artículo: <a href="http://blog.jdiezfoto.es/wp-content/uploads/2012/04/PresentacionInternet_public.pdf" target="_blank">Presentación &#8220;¿Qué es Internet?&#8221;</a>.</p>
<p>Espero que os haya resultado interesante el artículo y ya sepáis un poco más acerca de aquello que usamos todos los días y no sabemos que es lo que hay detrás de todo ello.</p>
<p>Finalmente quisiera agradecer desde aquí a Víctor Manuel López Millán, profesor de la Universidad San Pablo CEU, por su labor como profesor por conseguir desperar el interés por la materia y lo relacionado con ella y fomentar el auto-aprendizaje de esta manera.</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-2012 Juan Díez-Yanguas Barber </p></p>]]></content:encoded>
			<wfw:commentRss>http://blog.jdiezfoto.es/informatica/internet-que-es-y-como-funciona/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<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-2012 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-2012 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-2012 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-2012 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-2012 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-2012 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-2012 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-2012 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-2012 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-2012 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>5</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-2012 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-2012 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-2012 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-2012 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-2012 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-2012 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>5</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-2012 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-2012 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>
	</channel>
</rss>

<!-- Dynamic page generated in 1.581 seconds. -->
<!-- Cached page generated by WP-Super-Cache on 2012-05-19 20:37:49 -->
<!-- Compression = gzip -->
