Internet se construye sobre el protocolo de transmisión TCP (Transmision Control Protocol), y sobre un sistema de identificación de computadores que la forman basado en el protocolo IP:
La comunicación con TCP/IP se realiza mediante sockets, conexiones entre un computador y otro a través de la que se envían datos. Puede haber más de un socket entre dos mismos ordenadores, con lo que para distinguirlos se emplea un identificador, llamado puerto.
Se han desarrollado una serie de servicios y protocolos basados en TCP/IP y en la arquitectura cliente/servidor, donde una máquina (cliente) solicita peticiones de servicio a otra en la que suelen estar los datos y programas de aplicación (servidor). Algunos de los servicios y protocolos desarrollados son:
Para identificar los recursos de Internet se introdujeron las URL (Uniform Resource Locator), un esquema de nomenclatura de recursos basado en especificar el protocolo utilizado, el servidor y el recurso al que se accede:
Protocolo Servidor [:Puerto] Fichero
El protocolo depende del servicio al que se quiera acceder, y el fichero es la ruta del recurso, en el espacio de direcciones del servidor. Los protocolos de esta nomenclatura corresponden con algunos de los servicios mencionados:
Ejemplos de URL serían:
http://www.ua.es/index.htm ftp://ftp.dccia.ua.es/pub/winzip.exe mailto:pepe@yahoo.com
Los navegadores son clientes que permiten utilizar la mayoría de los protocolos anteriores. Traducen las URL en peticiones al servicio correspondiente.
El protocolo HTTP especifica el modo de comunicación entre una máquina cliente y una máquina servidor, de modo que el cliente solicita un documento del espacio de direcciones del servidor, y éste se lo sirve.
HTTP es un protocolo que no tiene estado: un cliente realiza una petición al servidor, que contesta y la transacción acaba, con lo que en la siguiente petición que pueda realizar el mismo cliente se deben proporcionar de nuevo todos los datos necesarios para que el servidor sirva correctamente la nueva petición, no habiendo ninguna relación entre las peticiones.
En el protocolo HTTP el cliente realiza una petición que se descompone en:
Comando URI ProtocoloPor ejemplo:
GET /index.html HTTP/1.1
Clave: ValorPor ejemplo:
Accept-Encoding: gzip, deflate User-Agent: Mozilla/4.0 (compatible;MSIE5.0;Windows 98)Tras las cabeceras, el cliente envía una línea en blanco (\r\n\r\n) para indicar el final de la sección de cabeceras.
METODO GET
El comando GET permitía al principio solicitar al servidor un documento estático, existente en su espacio de direcciones. Luego se vio que esto no era suficiente, y se introdujo la posibilidad de solicitar búsquedas al servidor, de forma que el documento no tuviera que ser necesariamente estático, sino que la búsqueda estuviera condicionada por unos determinados parámetros. Así, el comando GET tiene la forma:
GET direccion ? parametros version HTTP
Por ejemplo:
GET /cgi-bin/pagina.cgi?IDIOMA=C&MODELO=a+b HTTP/1.1
Los parámetros se indican con pares nombre=valor, separados por '&', y reciben el nombre de datos de formulario. El URI no puede contener espacios ni algunos caracteres, por lo que se utilizan códigos especiales, como el '+' para indicar espacio en blanco, u otros códigos %XX para representar otros caracteres. Uno de los trabajos más duros de los programas CGI es procesar esta cadena de parámetros para extraer la información necesaria.
OTROS METODOS
En la versión 1.1 de HTTP se definen otros métodos además de GET:
GET Y POST
Los dos métodos más comúnmente usados son GET y POST. Veremos las diferencias entre uno y otro con un ejemplo:
GET /dir/cargaPagina.php?id=21&nombre=Pepe HTTP/1.1 <cabeceras>
POST /dir/cargaPagina.php HTTP/1.1 <cabeceras> id=21&nombre=PepeVemos que los parámetros se pasan en el cuerpo de la petición, fuera de la línea del comando.
Comúnmente existen 3 formas de enviar una petición GET:
http://www.xx.com/pag.html?id=123&nombre=pepe
<a href="http://www.xx.com/pag.html?id=123&nombre=pepe"> Pulsa Aqui </a>
<html> <body> <form action="http://www.xx.com/pag.html"> <input type="text" name="id" value="123"> <input type="text" name="nombre" value="pepe"> <input type="submit" value="Enviar"> </form> </body> </html>
Para enviar una petición POST, normalmente se utiliza un formulario con METHOD=POST:
<html> <body> <form action="http://www.xx.com/pag.html" METHOD=POST> <input type="text" name="id" value="123"> <input type="text" name="nombre" value="pepe"> <input type="submit" value="Enviar"> </form> </body> </html>
Las respuestas del servidor también tienen tres partes:
HTTP/1.0 200 OK
Vamos a poder implementar programas que lean las cabeceras que envía un cliente (un navegador, por ejemplo) y que modifiquen el documento servido en función de dichas cabeceras (por ejemplo, enviar una página en función del idioma que se especifique). Por otra parte, podremos utilizar las cabeceras que envíe el servidor como respuesta para obligar al navegador a hacer determinadas acciones, como saltar a otra URL.
Veremos a continuación las cabeceras más comunes tanto en las peticiones de los clientes como en las respuestas de los servidores. La RFC donde se especifican estas cabeceras es la 2616.
CABECERAS DE PETICION (HTTP/1.1)
NOMBRE | DESCRIPCIÓN |
Accept | Tipos MIME que puede manejar el cliente |
Accept-Charset | Conjunto de caracteres que el cliente puede manejar |
Accept-Encoding | Define si el navegador puede aceptar datos codificados |
Accept-Language | Idiomas aceptados |
Authorization | Para identificarse cuando se accede a páginas protegidas |
Cache-Control | Opciones relacionadas con el servidor proxy. Esta cabecera se llamaba Pragma en HTTP 1.0 |
Connection | Define si el cliente es capaz de realizar conexiones persistentes (keep-alive, valor por defecto), o no (close). Nueva en HTTP 1.1 |
Content-Length | Longitud de los datos enviados. Aplicable a peticiones POST |
Content-Type | Tipo MIME de los datos enviados. Aplicable a peticiones POST |
Cookie | Para las cookies que se manejen |
From | Dirección de correo electrónico responsable de la petición |
Host | Unica cabecera requerida por HTTP 1.1. Indica el host y el puerto tal y como se especifica en la URL original. |
If-Modified-Since | El cliente sólo desea el documento si ha sido modificado después de la fecha indicada en esta cabecera. |
Referer | URL origen de la petición. Si estamos en la página 1 y pinchamos en un enlace a la página 2, la URL de la página 1 se incluye en esta cabecera cuando se realiza la petición de la página 2. |
User-Agent | Cliente que está realizando la petición (normalmente muestra datos del navegador, como nombre, etc). |
CABECERAS DE RESPUESTA
NOMBRE | DESCRIPCIÓN |
Allow | Métodos disponibles (GET, POST, etc) a los que puede responder el recurso que se está solicitando |
Cache-Control | Dice al cliente en qué circunstancias puede hacer una
caché del documento que está sirviendo:
Esta cabecera se llamaba Pragma en HTTP 1.0 |
Content-Encoding | Tipo de compresión (gzip, etc) en que se devuelve el documento solicitado |
Content-Language | Idioma en que está escrito el documento. En la RFC 1766 están los idiomas disponibles |
Content-Length | Número de bytes de la respuesta |
Content-MD5 | Una forma de fijar el checksum (verificación de integridad) del documento enviado |
Content-Type | Tipo MIME de la respuesta |
Date | Hora y fecha, en formato GMT, en que la respuesta ha sido generada |
Expires | Hora y fecha, en formato GMT, en que la respuesta debe considerarse caducada |
Last-Modified | Fecha en que el documento servido se modificó por última vez. Con esto, el documento se sirve sólo si su Last-Modified es mayor que la fecha indicada en el If-Modified-Since de la cabecera del cliente. |
Location | Indica la nueva URL donde encontrar el documento. Debe usarse con un código de estado de tipo 300. El navegador se redirigirá automáticamente a la dirección indicada en esta cabecera. |
Refresh | Indica al cliente que debe recargar la página
después de los segundos especificados. También puede indicarse la
dirección de la página a cargar después de los segundos
indicados:Refresh: 5; URL=http://www.unapagina.com |
Set-Cookie | Especifica una cookie asociada a la página |
WWW-Authenticate | tipo de autorización y dominio que debería indicar el cliente en su cabecera Authorization. |
Para colocar estas cabeceras en un documento se tienen varios métodos, dependiendo de cómo estemos tratando las páginas (mediante servlets, HTML, etc). Por ejemplo, con HTML podemos enviar cabeceras mediante etiquetas META en la cabecera (<HEAD>) de la página HTML:
<META HTTP-EQUIV="Cabecera" CONTENT="Valor">
Por ejemplo:
<META HTTP-EQUIV="Location" CONTENT="http://www.unapagina.com">
El código de estado que un servidor devuelve a un cliente en una petición indica el resultado de dicha petición. Se tiene una descripción completa de los mismos en el RFC 2616. Están agrupados en 5 categorías:
200 OK Todo está bien 204 No Content No hay documento nuevo
301 Moved Permanently El documento está en otro lugar, indicado en la cabecera Location 302 Found Como el anterior, pero la nueva URL es temporal, no permanente. 304 Not Modified El documento pedido no ha sufrido cambios con respecto al actual (para cabeceras If-Modified-Since)
400 Bad Request Mala sintaxis en la petición 401 Unauthorized El cliente no tiene permiso para acceder a la página. Se debería devolver una cabecera WWW-Authenticate para que el usuario introduzca login y password 403 Forbidden El recurso no está disponible 404 Not Found No se pudo encontrar el recurso 408 Request Timeout El cliente tarda demasiado en enviar la petición
500 Internal Server Error Error en el servidor 501 Not Implemented El servidor no soporta la petición realizada 504 Gateway Timeout Usado por servidores que actúan como proxies o gateways, indica que el servidor no obtuvo una respuesta a tiempo de un servidor remoto
Las cookies son un mecanismo general mediante el que los programas de un servidor web pueden almacenar información en la parte del cliente de la conexión. Es una forma de añadir estado a las conexiones HTTP, aunque el manejo de cookies no es parte del protocolo HTTP, pero es soportado por la mayoría de los clientes.
Las cookies son objetos de tipo:
nombre = valor
donde se asigna un valor determinado (una cadena de texto) a una variable del nombre indicado. Dicho objeto es almacenado y recordado por el servidor web y el navegador durante un período de tiempo (indicado como un parámetro interno de la propia cookie). Así, se puede tener una lista de cookies con distintas variables y distintos valores, para almacenar información relevante para cada usuario (se tienen listas de cookies independientes para cada usuario).
El funcionamiento es: el servidor, con la cabecera Set-Cookie, envía al cliente información de estado que éste almacenará. Entre la información se encuentra la descripción de los rangos de URLs para los que este estado es válido, de forma que para cualquier petición HTTP a alguna de esas URLs el cliente incluirá esa información de estado, utilizando la cabecera Cookie.
La sintaxis de la cabecera Set-Cookie es:
Set-Cookie: CLAVE1=VALOR1;...;CLAVEN=VALORN [OPCIONES]
donde OPCIONES es una lista opcional con cualquiera de estos atributos:
expires=FECHA;path=PATH;domain=DOMINIO;secure
expires=Wed, 09-Nov-1999 23:12:40 GMT
Por otra parte, cuando el cliente solicita una URL que empareja con el dominio y path de alguna cookie, envía la cabecera:
Cookie: CLAVE1=VALOR1;CLAVE2=VALOR2;...;CLAVEN=VALORN
El número máximo de cookies que está garantizado que acepte cualquier navegador es de 300, con un máximo de 20 por cada servidor o dominio. El tamaño máximo de una cookie es de 4096 bytes.
RFC: los documentos RFC (Request For Comment) forman un conjunto de notas acerca de Internet. Tratan sobre diferentes aspectos de la comunicación entre computadores. Podemos encontrar información sobre todos los RFC en http://www.rfc-editor.org. Si conocemos el número de RFC, normalmente podemos encontrar el documento en http://www.rfc-editor.org/rfc/rfcXXXX.txt (sindo XXXX el número de RFC).
MIME: MIME (Multipurpose Internet Mail Extensions) es un estándar oficial de Internet que indica cómo se deben formatear los mensajes para que puedan intercambiarse entre diferentes sistemas de correo electrónico. Permite incluir cualquier tipo de dato (texto, audio, video, imágenes, etc). Las RFC que definen los tipos MIME son la 2045, 2046, 2047, 2048 y 2049. Algunos tipos comunes son:
image/jpeg: imagen JPEG
image/png: imagen PNG
video/mpeg: película MPEG
GMT: el formato de fecha y hora GMT tiene la siguiente estructura:
Wdy, DD Mon YYYY HH:MM:SS GMT
donde:
HH:MM:SS indica la hora, minuto y segundo, en formato de 24 horas (01:02:33, 21:15:58, etc)
Esta representación está basada en las RFC 822, 1036 y 1123
Veremos ahora algunos mecanismos que pueden emplearse con HTTP para autentificar (validar) al usuario que intenta acceder a un determinado recurso.
El protocolo HTTP incorpora un mecanismo de autentificación básico (basic) basado en cabeceras de autentificación para solicitar datos del usuario (el servidor) y para enviar los datos del usuario (el cliente), de forma que comprobando la exactitud de los datos se permitirá o no al usuario acceder a los recursos. Esta autentificación no proporciona confidencialidad ni integridad, sólo se emplea una codificación Base64.
Una variante de esto es la autentificación digest, donde, en lugar de transmitir el password por la red, se emplea un password codificado. Dicha codificación se realiza tomando el login, password, URI, método HTTP y un valor generado aleatoriamente, y todo ello se combina utilizando el método de encriptado MD5, muy seguro. De este modo, ambas partes de la comunicación conocen el password, y a partir de él pueden comprobar si los datos enviados son correctos. Sin embargo, algunos servidores no soportan este tipo de autentificación.
Las aplicaciones reales pueden requerir un nivel de seguridad mayor que el proporcionado por las autentificaciones basic o digest. También pueden requerir confidencialidad e integridad aseguradas. Todo esto se consigue mediante los certificados digitales.
A.3.2.1. Criptografía de clave pública
La clave de los certificados digitales reside en la criptografía de clave pública, mediante la cual cada participante en el proceso tiene dos claves, que le permiten encriptar y desencriptar la información. Una es la clave pública, que se distribuye libremente. La otra es la clave privada, que se mantiene secreta. Este par de claves es asimétrico, es decir, una clave sirve para desencriptar algo codificado con la otra. Por ejemplo, supongamos que A quiere enviar datos encriptados a B. Para ello, hay dos posibilidades:
- A toma la clave pública de B, codifica con ella los datos y se los envía. Luego B utiliza su clave privada (que sólo él conoce) para desencriptar los datos.
- A toma su clave privada, codifica los datos y se los envía a B, que toma la clave pública de A para descodificarlos. Con esto, B sabe que A es el remitente de los datos.
El encriptado con clave pública se basa normalmente en el algoritmo RSA, que emplea números primos grandes para obtener un par de claves asimétricas. Las claves pueden darse con varias longitudes; así, son comunes claves de 1024 o 2048 bits.
A.3.2.2. Certificados digitales
Lógicamente, no es práctico teclear las claves del sistema de clave pública, pues son muy largas. Lo que se hace en su lugar es almacenar estas claves en disco en forma de certificados digitales. Estos certificados pueden cargarse por muchas aplicaciones (servidores web, navegadores, gestores de correo, etc).
Notar que con este sistema se garantiza la confidencialidad (porque los datos van encriptados), y la integridad (porque si los datos se desencriptan bien, indica que son correctos). Sin embargo, no proporciona autentificación (B no sabe que los datos se los ha enviado A), a menos que A utilice su clave privada para encriptar los datos, y luego B utilice la clave pública de A para desencriptarlos. Así, B descodifica primero el mensaje con su clave privada, y luego con la pública de A. Si el proceso tiene éxito, los datos se sabe que han sido enviados por A, porque sólo A conoce su clave privada.
A.3.2.3. SSL
SSL (Secure Socket Layer) es una capa situada entre el protocolo a nivel de aplicación (HTTP, en este caso) y el protocolo a nivel de transporte (TCP/IP). Se encarga de gestionar la seguridad mediante criptografía de clave pública que encripta la comunicación entre cliente y servidor. La versión 2.0 de SSL (la primera mundialmente aceptada), proporciona autentificación en la parte del servidor, confidencialidad e integridad. Funciona como sigue:
- Un cliente se conecta a un lugar seguro utilizando el protocolo HTTPS (HTTP + SSL). Podemos detectar estos sitios porque las URLs comienzan con https://
- El servidor envía su clave pública al cliente.
- El navegador comprueba si la clave está firmada por un certificado de confianza. Si no es así, pregunta al cliente si quiere confiar en la clave proporcionada.
SSL 3.0 proporciona también soporte para certificados y autentificación del cliente. Funcionan de la misma forma que los explicados para el servidor, pero residiendo en el cliente.
Hemos visto el protocolo HTTP, pero no cómo utilizarlo para implementar una aplicación.
En el lado del servidor, tenemos que conseguir que nuestro servidor HTTP sea capaz de ejecutar programas de aplicación que recojan los parámetros de peticiones del cliente, los procesen y devuelvan al servidor un documento que éste pasará a su vez al cliente.
Así, para el cliente el servidor no habrá hecho nada distinto a lo estipulado en el protocolo HTTP, pero el servidor podrá valerse de herramientas externas para procesar y servir la petición solicitada, pudiendo así no limitarse a servir páginas estáticas, sino utilizar otras aplicaciones (servlets, JSP, PHP, etc) para servir documentos con contenido dinámico.
Los programas de aplicación son típicamente programas que realizan consultas a bases de datos, procesan la información resultante y devuelven la salida al servidor, entre otras tareas.
Se tienen muchas tecnologías relacionadas con extensiones del lado del cliente (entendiendo cliente como un navegador que interpreta código HTML). El código HTML es un código estático que sólo permite formatear la apariencia de una página y definir enlaces a otras páginas o URLs. Esto no es suficiente si queremos que el navegador realice funciones más complicadas: validar entradas de formularios, mostrar la evolución del precio de unas acciones, etc.
Para ampliar las funcionalidades del navegador (respetando el protocolo HTTP), se utilizan tecnologías como JavaScript, Applets, Flash, etc. Estas se basan en hacer que el navegador ejecute código que le pasa el servidor, bien embebido en documentos HTML (como es el caso de JavaScript), o bien mediante ficheros compilados multiplataforma (como es el caso de los Applets Java o los ficheros Flash).
Como ejercicio acerca del protocolo HTTP, practicaremos con unos comandos HTTP y veremos la forma de trabajar del protocolo. Nos vamos a basar para ello en algunas herramientas:
En este ZIP tenéis disponible un ejemplo de funcionamiento de cliente y servidor HTTP. El ZIP tiene 4 clases Java:
Para probar esta utilidad, primero debemos colocarnos en el directorio donde están, y compilarlas. Luego las probamos siguiendo los pasos:
1. El servidor
Para ejecutar el servidor, escribimos:
java ServidorHTTP
Aparecerá una ventana como la siguiente:
Figura 1. Ejemplo de aplicación servidor HTTP
En el cuadro superior indicamos el puerto por el que escuchará las peticiones de los clientes. Luego, pulsando en Esperar Petición se quedará a la espera de que algún cliente el envíe alguna petición
2. El cliente
Para ejecutar el cliente, escribimos:
java ClienteHTTP
Aparecerá una ventana como la siguiente:
Figura 2. Ejemplo de aplicación cliente HTTP
En los cuadros superiores indicamos la dirección del servidor al que nos conectamos (127.0.0.1, por ejemplo), y el puerto por el que dicho servidor está esperando peticiones (por defecto es el 80). Pulsando el botón de Conectar nos conectaremos con el servidor.
En el cuadro de petición del cliente escribimos el comando HTTP que le queremos enviar al servidor. Por ejemplo:
GET / HTTP/1.1 Host:127.0.0.1 <2 veces Intro para el salto de linea tras las cabeceras>
Luego, pulsando en Enviar se quedará a la espera de que el servidor le envíe la respuesta.
3. Ultimos pasos
Tras enviar el cliente la petición, en el cuadro Petición del cliente del programa servidor nos aparecerá esa misma petición.
Ahora, el servidor debe responder. Para ello, en el cuadro Respuesta del servidor (dentro de la aplicación servidor) escribimos algo como:
HTTP/1.1 200 OK <2 veces Intro para el salto de linea tras las cabeceras>
Pulsando el botón de Enviar en el servidor se enviará esta respuesta, que aparecerá en el cuadro Respuesta del servidor de la aplicación cliente.
4. Conexión con un servidor real
Podemos utilizar la aplicación cliente para conectar con un servidor real y ver lo que devuelve. Para ello, por ejemplo ponemos como host:
www.ua.es
Luego le damos al botón de Conectar, y en el cuadro de Petición del cliente escribimos:
GET / HTTP/1.1 Host:www.ua.es <2 veces Intro para el salto de linea tras las cabeceras>
Y el servidor nos devolverá algo como:
HTTP/1.1 200 OK Age:965 Date: Thu,24 Oct 2002 20:52:13 GMT Content-Length:2657 Content-Type=text/html ... <!DOCTYPE...> ...
En este ZIP tenéis otra utilidad para poder probar el protocolo HTTP. Se trata de la herramienta WebClient, desarrollada por el autor del libro Core Servlets And JavaServer Pages, para probar sus ejemplos. Es un fichero JAR que simula un cliente HTTP (el servidor al que conectar será cualquier servidor que se tenga disponible: el de nuestra máquina, o uno remoto).
Se ejecuta con:
java -jar WebClient.jar
Aparece luego una ventana como esta:
Figura 3. WebClient
En ella pondremos:
GET / HTTP/1.1
Host:www.ua.es
Tras enviar los datos de la petición, nos aparece abajo la respuesta del servidor (la misma que con la aplicación anterior):
HTTP/1.1 200 OK Age:965 Date: Thu,24 Oct 2002 20:52:13 GMT Content-Length:2657 Content-Type=text/html ... <!DOCTYPE...> ...
El funcionamiento visto con los ejemplos de clientes HTTP anteriores es el mismo que el que emplean los navegadores, sólo que ellos permiten configurar las cabeceras de otra forma, y no presentan la respuesta del servidor como texto plano, sino que dan formato al documento enviado.