Anda di halaman 1dari 17

DESARROLLO WEB EN

ENTORNO SERVIDOR

UT6.- Desarrollo de aplicaciones Web


utilizando cdigo embebido

Departamento de Informtica y Comunicaciones


CFGS Desarrollo de Aplicaciones Web
Segundo Curso
IES Virrey Morcillo
Villarrobledo (Albacete)

ndice
1. Introduccin .......................................................................................................................................................................................................1
2. Mantenimiento del estado ...........................................................................................................................................................................1
2.1. Administracin de estado basada en cliente .............................................................................................................................2
2.2. Administracin de estado basada en servidor .........................................................................................................................3
3. Manejo de cookies ...........................................................................................................................................................................................4
3.1. Configuracin de cookies desde HTTP.........................................................................................................................................5
3.2. Ejemplo de uso de cookies ................................................................................................................................................................7
4. Seguimiento de sesin de un cliente web .............................................................................................................................................9
4.1. Funcionalidad de sesin bsica .......................................................................................................................................................9
4.2. Uso de cookies con sesiones .......................................................................................................................................................... 10
4.3. Almacenamiento del identificador de sesin ......................................................................................................................... 10
4.4. Inicio de sesin .................................................................................................................................................................................... 10
4.5. Registro de variables de sesin .................................................................................................................................................... 11
4.6. Uso de variables de sesin.............................................................................................................................................................. 11
4.7. Anulacin del registro de variables y eliminar la sesin .................................................................................................. 11
4.8. Ejemplo de uso de variables de sesin ..................................................................................................................................... 11
5. Seguridad en aplicaciones Web .............................................................................................................................................................. 13
5.1. Implementar tecnologa de seguridad ...................................................................................................................................... 13
5.2. Modelo de amenazas ......................................................................................................................................................................... 13
5.3. Recomendaciones de seguridad para aplicaciones Web .................................................................................................. 14

Desarrollo Web en Entorno Servidor.

UT6.- Desarrollo de aplicaciones Web utilizando cdigo embebido.

1. Introduccin
Las aplicaciones Web fueron concebidas para mostrar contenidos estticos, es decir, informacin no
cambiante en funcin del tiempo, lo que equivale a decir que ante diversas peticiones del mismo recurso,
siempre se obtiene como respuesta el mismo contenido. Por este motivo, no exista la necesidad de almacenar el
estado de las aplicaciones Web, pues las acciones realizadas y los datos introducidos de forma previa a la
peticin de un recurso eran irrelevantes.
En este sentido, el protocolo HTTP, que es el protocolo sobre el que se basa la comunicacin de
contenidos Web, se dise sin estado. Esta carencia no debera tildarse de defecto, pues el hecho de no tener que
reservar recursos para almacenar el estado proporciona una elevada escalabilidad para compartir informacin,
ya que los requisitos de memoria necesarios son mucho ms reducidos. De hecho, esta elevada escalabilidad ha
permitido, entre otras cosas, la rpida extensin de contenidos Web. Por otra parte, dado que los contenidos de
las aplicaciones Web han ido cambiando con el paso del tiempo, ya sea incluyendo informacin dinmica
dependiente del usuario conectado o incluyendo contenidos multimedia, aparece la necesidad de almacenar
acciones realizadas o datos introducidos previamente, es decir, se requiere almacenar el estado de la aplicacin.
Ante esta necesidad, el primer objetivo que se plantea es la eleccin de un mecanismo apropiado para el
almacenamiento del estado. De hecho, existe una propuesta (RFC2109), comnmente conocida como cookies,
que pretende dotar de un mecanismo estndar para manejar el estado.
No obstante, a pesar de que la mayora de los navegadores permiten el uso de cookies, no se ha
convertido en el nico mecanismo utilizado para almacenar el estado, sino que coexiste con otros, como pueden
ser los campos ocultos, el ViewState o las variables de sesin. Gracias a que existen diferentes alternativas a la
hora de almacenar la informacin de estado, es necesario identificar los factores ms relevantes que
determinarn la eleccin del mecanismo apropiado para la gestin del estado, que son, entre otros: el tamao y
tipo de la informacin a almacenar, la duracin temporal de la informacin, la velocidad de almacenado y
recuperacin y los factores de seguridad.

2. Mantenimiento del estado


Cada vez que la pgina se enva al servidor, se crea una nueva instancia de la clase de la pgina Web. En
la programacin Web tradicional, esto se traduce en que toda la informacin asociada a la pgina y sus controles
se pierden con cada recorrido de ida y vuelta. Por ejemplo, si un usuario escribe informacin en un cuadro de
texto, dicha informacin se perder en el recorrido de ida y vuelta desde el explorador o dispositivo cliente al
servidor.
Para superar esta limitacin inherente de la programacin Web tradicional, los lenguajes del lado del
servidor incluyen varias opciones que ayudan a preservar los datos en cada pgina y en toda la aplicacin. Estas
caractersticas son las siguientes:

Estado de vista
Estado de control
Campos ocultos
Cookies
Cadenas de consulta
Estado de aplicacin
Estado de sesin
Propiedades de perfiles

Las caractersticas de estado de vista, estado de control, campos ocultos, cookies y cadenas de consulta
almacenan todas ellas datos en el cliente de formas distintas, mientras que las caractersticas de estado de
aplicacin, estado de sesin y propiedades de perfil almacenan los datos en la memoria del servidor. Cada opcin
tiene ventajas y desventajas, dependiendo del escenario.

IES Virrey Morcillo. Departamento de Informtica y Comunicaciones.

Desarrollo Web en Entorno Servidor.

UT6.- Desarrollo de aplicaciones Web utilizando cdigo embebido.

2.1. Administracin de estado basada en cliente


Los siguientes apartados describen opciones para administrar el estado que almacenan la informacin
en la pgina o en el equipo cliente. En estas opciones, la informacin no se conserva en el servidor entre acciones
de ida y vuelta, y son las siguientes:
a) Estado de vista:
La propiedad ViewState proporciona un objeto de diccionario para conservar valores entre las distintas
solicitudes de una misma pgina. ste es el mtodo predeterminado que la pgina utiliza para conservar
los valores de las propiedades de la propia pgina y sus controles entre recorridos de ida y vuelta.
Cuando se procesa la pgina, se calcula el valor de hash del estado actual de la pgina y de los controles
en una cadena y se guarda en la pgina como campo oculto o varios campos ocultos si el volumen de los
datos almacenados en la propiedad ViewState sobrepasa un valor especificado. Cuando se vuelve a
enviar la pgina al servidor, sta analiza la cadena de estado de vista durante su inicializacin y la
informacin de las propiedades se restablece en ella.
En un estado de vista se puede tambin almacenar valores.
b) Estado de control:
En ocasiones es necesario almacenar los datos del estado de control para que un control funcione
correctamente. Por ejemplo, si ha escrito un control personalizado con varias fichas que muestran
distintos tipos de informacin, el control debe saber la ficha que se selecciona en los recorridos de ida y
vuelta para que funcione tal y como se espera. La propiedad ViewState se puede utilizar para este
propsito, pero los desarrolladores pueden desactivar el estado de vista en el nivel de pgina,
interrumpiendo su control eficazmente. Para resolver este problema, el marco de trabajo de la pgina
cuenta con una caracterstica denominada "estado de control".
La propiedad ControlState permite mantener la informacin de las propiedades que es especfica de un
control y que no se puede desactivar como ocurre con la propiedad ViewState.
c) Campos ocultos:
Algunos lenguajes del lado del servidor permiten almacenar informacin en un control HiddenField, que
se representa como campo oculto estndar HTML. Un campo oculto no est visible en el explorador,
pero se pueden configurar sus propiedades igual que las de un control estndar. Cuando se enva una
pgina al servidor, el contenido del campo oculto se enva en la coleccin Form de HTTP junto con los
valores de otros controles. Un campo oculto acta como repositorio de cualquier informacin especfica
de pgina que desee almacenar directamente en la pgina.
Un control HiddenField almacena una nica variable en su propiedad Value y se debe agregar en la
pgina de forma explcita.
Para que los valores de los campos ocultos estn disponibles durante el procesamiento de la pgina,
debe enviarla mediante el mtodo POST de HTTP. Si utiliza campos ocultos y una pgina se procesa
como respuesta a un vnculo o a un comando GET de HTTP, los campos ocultos no estarn disponibles.
d) Cookies:
Una cookie es una cantidad pequea de datos que se almacena en un archivo de texto en el sistema de
archivos del cliente o que se mantiene en la memoria durante la sesin del explorador cliente. Contiene
informacin especfica del sitio que el servidor enva al cliente junto con el resultado de la pgina. Las
cookies pueden ser temporales (con fechas y horas de caducidad especficas) o permanentes.
Las cookies se pueden utilizar para almacenar informacin acerca de un cliente, sesin o aplicacin
especficos. Las cookies se guardan en el dispositivo cliente y, cuando el explorador solicita una pgina,
el cliente enva la informacin de la cookie junto con la informacin de la solicitud. El servidor puede
leer la cookie y extraer su valor. Uno de los usos tpicos es almacenar un smbolo (puede que cifrado)
que indica que el usuario ya se ha autenticado en la aplicacin.
El explorador slo puede devolver los datos al servidor que cre la cookie. Sin embargo, algunos
usuarios malintencionados cuentan con medios para tener acceso a las cookies y leer su contenido. Se
recomienda no almacenar informacin confidencial, como el nombre de usuario o la contrasea, en una
cookie. En su lugar, se almacena un smbolo en la cookie que identifique al usuario y, a continuacin, se
utiliza el smbolo para buscar la informacin confidencial en el servidor.

IES Virrey Morcillo. Departamento de Informtica y Comunicaciones.

Desarrollo Web en Entorno Servidor.

UT6.- Desarrollo de aplicaciones Web utilizando cdigo embebido.

e) Cadenas de consulta:
Una cadena de consulta es informacin que se anexa al final de la direccin URL de una pgina. Un
ejemplo tpico de cadena de consulta podra tener el siguiente aspecto:
http://www.contoso.com/listwidgets.aspx?category=basic&price=100
En la ruta URL indicada, la cadena de consulta empieza por un signo de interrogacin (?) e incluye dos
pares de atributo-valor, uno de ellos se denomina "category" y el otro, "price".
Las cadenas de consulta proporcionan una manera sencilla pero limitada de mantener la informacin de
estado. Por ejemplo, es una manera sencilla de pasar informacin de una pgina a otra, por ejemplo,
pasar un cdigo de producto de una pgina a otra donde se procesar. Sin embargo, en algunos
exploradores y dispositivos de cliente la longitud de la direccin URL tiene una limitacin de 2083
caracteres.
Para que los valores de las cadenas de consulta estn disponibles durante el procesamiento de la pgina,
debe enviar la pgina utilizando el mtodo GET de HTTP. Es decir, no puede utilizar las cadenas de
consulta si la pgina se procesa como respuesta a un mtodo POST de HTTP.

2.2. Administracin de estado basada en servidor


Los lenguajes de programacin Web del lado del servidor proporcionan una serie de medios para
mantener la informacin de estado en el servidor, en lugar de conservarla en el cliente. Con la administracin de
estados basada en servidor, se puede reducir la cantidad de informacin que se enva al cliente para conservar el
estado, sin embargo, puede suponer un uso excesivo de los recursos del servidor. En los apartados siguientes se
describen tres caractersticas de la administracin de estados basada en servidor:
a) Estado de aplicacin:
Se permite guardar valores utilizando el estado de sesin de cada aplicacin Web activa. El estado de
aplicacin es un mecanismo de almacenamiento global al que se puede obtener acceso desde todas las
pginas de la aplicacin Web. Por tanto, el estado de aplicacin resulta til para almacenar la
informacin que se debe mantener en los recorridos de ida y vuelta del servidor y entre las solicitudes
de las pginas.
El estado de aplicacin se almacena en un diccionario de tipo clave-valor que se crea cada vez que se
enva una solicitud a una direccin URL especfica. Se puede agregar informacin especfica de la
aplicacin a esta estructura para almacenarla entre las peticiones de pgina. Despus de agregar la
informacin especfica de la aplicacin a estado de aplicacin, el servidor se encarga de administrarla.
b) Estado de sesin:
Se permite guardar valores utilizando el estado de sesin de cada sesin de una aplicacin Web activa. El
estado de sesin es similar a estado de aplicacin, con la diferencia de que el mbito es la actual sesin
del explorador. Si hay varios usuarios utilizando la aplicacin, cada uno de ellos tendr un estado de
sesin distinto. Asimismo, si un usuario sale de la aplicacin y vuelve ms tarde, el segundo usuario
tendr un estado de sesin distinto al del primero.
El estado de sesin tiene la estructura de un diccionario de tipo clave-valor para almacenar informacin
especfica de cada sesin que se debe conservar en recorridos de ida y vuelta del servidor, as como
entre solicitudes de pginas.
Se puede utilizar el estado de sesin para llevar a cabo las tareas siguientes:
Identificar unvocamente las peticiones del explorador o del dispositivo de cliente y asignarlas a
una instancia de sesin individual en el servidor.
Almacenar en el servidor datos especficos de la sesin para utilizarlos a travs de mltiples
peticiones del explorador o dispositivo dentro de la misma sesin.
Producir eventos de administracin de sesin adecuados. Adicionalmente, puede escribir cdigo
de aplicacin para aprovechar estos eventos.
Despus de agregar la informacin especfica de la aplicacin a estado de sesin, el servidor se encarga
de administrar dicho objeto. En funcin de las opciones especificadas, la informacin de la sesin se
puede almacenar en cookies, en un servidor que no forme parte del proceso, o en un equipo que ejecute
el Sistema Gestor de Bases de Datos.

IES Virrey Morcillo. Departamento de Informtica y Comunicaciones.

Desarrollo Web en Entorno Servidor.

UT6.- Desarrollo de aplicaciones Web utilizando cdigo embebido.

c) Propiedades de perfiles:
Se permite almacenar datos especficos del usuario. Esta caracterstica es similar al estado de sesin,
salvo que los datos del perfil no se pierden cuando caduca la sesin de un usuario. La caracterstica
propiedades de perfiles utiliza un perfil, que se guarda en un formato persistente y que se asocia con un
usuario especfico. El perfil permite administrar con facilidad la informacin sobre el usuario sin que sea
necesario crear y mantener una base de datos propia. Adems, el perfil hace que la informacin del
usuario est disponible mediante una API con establecimiento inflexible de tipos a la que puede obtener
acceso desde cualquier punto de la aplicacin. Se pueden almacenar objetos de cualquier tipo en el
perfil. La caracterstica de perfil proporciona un sistema de almacenamiento genrico que permite
definir y mantener casi cualquier tipo de datos mientras stos sigan estando disponibles en un modo de
seguridad de tipos.

3. Manejo de cookies
Las cookies proporcionan un medio para almacenar informacin especfica del usuario en las
aplicaciones Web. Por ejemplo, cuando un usuario visita un sitio, las cookies pueden emplearse para almacenar
las preferencias del usuario u otra informacin. Cuando el usuario visite el sitio Web de nuevo, la aplicacin
podr recuperar la informacin que almacen previamente.
Una cookie es un pequeo fragmento de texto que acompaa a las solicitudes y a las pginas mientras
stas se transmiten del servidor Web al explorador y viceversa. La cookie contiene informacin que la aplicacin
Web puede leer cada vez que el usuario visita el sitio. Por ejemplo, si un usuario solicita una pgina de un sitio y
la aplicacin no solo enva una pgina, sino tambin una cookie que contiene la fecha y la hora, cuando el
explorador del usuario obtenga la pgina, tambin obtendr la cookie, que se almacenar en una carpeta en el
disco duro del usuario. Ms adelante, si el usuario solicita de nuevo una pgina del mismo sitio, cuando
introduzca la direccin URL, el explorador buscar en el disco duro local una cookie asociada a dicha direccin. Si
la cookie existe, el explorador la enviar al sitio junto con la solicitud de la pgina. A continuacin, la aplicacin
podr determinar la fecha y hora en que el usuario visit el sitio por ltima vez. Podra utilizar dicha informacin
para mostrar un mensaje al usuario o comprobar una fecha de caducidad.
Las cookies estn asociadas a un sitio Web, no a una pgina especfica, por lo que el explorador y el
servidor intercambiarn informacin de cookies independientemente de la pgina que el usuario solicite en su
sitio. Todos los sitios que visita el usuario pueden enviar una cookie al explorador del usuario; ste las
almacenar independientemente.
Las cookies permiten a los sitios Web almacenar informacin sobre los visitantes. De forma ms general,
las cookies son una manera de mantener la continuidad en una aplicacin Web, es decir, de realizar la
administracin de estados. Excepto durante los breves momentos en los que estn realmente intercambiando
informacin, el explorador y el servidor Web estn desconectados. Las solicitudes que realiza un usuario a un
servidor Web se tratan por separado unas de las otras. Sin embargo, muchas veces, es til para el servidor Web
reconocer a los usuarios cuando solicitan una pgina. Por ejemplo, el servidor Web de un sitio de compras
efecta el seguimiento de cada uno de los compradores para poder administrar los carros de la compra y la
informacin especfica del usuario. Por consiguiente, una cookie acta como una especie de tarjeta de llamada,
que presenta la identificacin necesaria para que la aplicacin sepa cmo continuar.
Las cookies se utilizan para muchos propsitos, todos ellos destinados a facilitar al sitio Web el
reconocimiento de los usuarios. Por ejemplo, un sitio que lleva a cabo un sondeo podra utilizar una cookie
simplemente como un valor booleano para indicar si el explorador del usuario ya ha participado en la votacin, a
fin de evitar que el usuario vote dos veces. Un sitio que solicita a un usuario que inicie una sesin podra utilizar
una cookie para registrar dicho inicio de sesin a fin de que el usuario no tenga que seguir proporcionando sus
credenciales.
La mayora de los exploradores admiten cookies de un tamao mximo de 4096 bytes. Debido a este
lmite, es recomendable utilizar las cookies para almacenar pequeas cantidades de datos, o mejor an, un
identificador como un id. de usuario. Este id. se puede utilizar para identificar al usuario y leer informacin
relativa a ste de una base de datos u otro almacn de datos.

IES Virrey Morcillo. Departamento de Informtica y Comunicaciones.

Desarrollo Web en Entorno Servidor.

UT6.- Desarrollo de aplicaciones Web utilizando cdigo embebido.

Los exploradores tambin imponen limitaciones respecto al nmero de cookies que cada sitio puede
almacenar en el equipo del usuario. La mayora de los exploradores slo permiten 20 cookies por sitio; si se
intenta almacenar ms, las cookies ms antiguas se descartan. Algunos exploradores tambin definen un lmite
absoluto, normalmente 300, en cuanto al nmero de cookies que aceptan desde todos los sitios en conjunto.
Una limitacin de las cookies con la que podra encontrarse es que los usuarios pueden configurar sus
exploradores para rechazarlas.
Tambin se puede establecer la fecha y hora de caducidad de una cookie. El explorador elimina las
cookies caducadas cuando un usuario visita el sitio que las escribi. La caducidad de una cookie debera
establecerse en funcin del tiempo que su aplicacin considere que el valor de la misma seguir siendo vlido.
Para que una cookie no caduque nunca, se puede establecer la fecha de caducidad en 50 aos a partir de ahora.
Si no se establece la caducidad de la cookie, sta se crea pero no se almacena en el disco duro del
usuario. En su lugar, la cookie se mantiene como parte de la informacin de sesin del usuario. Cuando el usuario
cierra el explorador, la cookie se descarta. Una cookie no persistente de este tipo resulta til para la informacin
que se debe almacenar durante perodos cortos de tiempo o que, por motivos de seguridad, no se debera
escribir en el disco del equipo cliente. Por ejemplo, las cookies no persistentes son tiles si el usuario est
trabajando en un equipo pblico en cuyo disco no desea que se escriba la cookie.
Se puede definir una cookie en el equipo de un usuario si enva un encabezado HTTP que contenga datos
con el siguiente formato:
Set-Cookie: NOMBRE=VALOR; [expires=FECHA;] [path=RUTA;] [domain=DOMINIO;] [secure]

De esta forma se crea una cookie con el nombre NOMBRE y con el valor VALOR. El resto de parmetros
son opcionales. El campo expires establece la fecha hasta la cual ser vlida la cookie. Si no se establece una fecha
de caducidad, la cookie ser permanente a menos que la eliminemos manualmente. Los campos path y domain se
pueden utilizar de forma conjunta para especificar el o los URL para los que se utiliza la cookie. La palabra
reservada secure indica que la cookie no se enviar a travs de una conexin HTTP.
Cuando un navegador se conecta a un URL, primero busca las cookies almacenadas localmente. Si
ninguna de ellas es relevante para el URL al que se ha conectado, se devuelven al servidor.

3.1. Configuracin de cookies desde HTTP


Se pueden configurar cookies manualmente en PHP por medio de la funcin setcookie(). Su sintaxis es la
siguiente:
bool setcookie ( string $name [, string $value [, int $expire = 0 [, string $path [, string
$domain [, bool $secure = false [, bool $httponly = false ]]]]]] )

Los parmetros se corresponden exactamente a los del encabezado Set-Cookie mencionado


anteriormente, es decir:
name
El nombre de la cookie.
value
El valor de la cookie. Este valor se guarda en el computador del cliente; no almacene informacin
sensible. Asumiendo que el name es 'cookiename', este valor se obtiene con $_COOKIE['cookiename'].
expire
El tiempo en el que expira la cookie. Es una fecha Unix por tanto est en nmero de segundos a partir
de la presente poca. En otras palabras, probablemente utilizar la funcin time() ms el nmero de
segundos que quiere que dure la cookie. Tambin se podra utilizar la funcin mktime().
time()+60*60*24*30 configurar la cookie para expirar en 30 das. Si se pone 0, o se omite, la cookie
expirar al final de la sesin (al cerrarse el navegador).

IES Virrey Morcillo. Departamento de Informtica y Comunicaciones.

Desarrollo Web en Entorno Servidor.

UT6.- Desarrollo de aplicaciones Web utilizando cdigo embebido.

El parmetro expire recibe una fecha Unix, por oposicin al formato de fecha Wdy, DD-Mon-YYYY
HH:MM:SS GMT, esto se debe a que PHP realiza esta conversin internamente.
path
La ruta dentro del servidor en la que la cookie estar disponible. Si se utiliza '/', la cookie estar
disponible en la totalidad del domain. Si se configura como '/prueba/', la cookie slo estar
disponible dentro del directorio /prueba/ y todos sus sub-directorios en el domain, tales como
/prueba/bar/. El valor por defecto es el directorio actual en donde se est configurando la cookie.
domain
El dominio para el cual la cookie est disponible. Establecer el dominio a 'www.example.com' har
que la cookie est disponible en el subdominio www y subdominios superiores. Las cookies
disponibles en un dominio inferior, como 'example.com', estarn disponibles en dominios superiores,
como 'www.example.com'.
secure
Indica que la cookie slo debiera transmitirse por una conexin segura HTTPS desde el cliente.
Cuando se configura como TRUE, la cookie slo se crear si es que existe una conexin segura. Del
lado del servidor, depende del programador el enviar este tipo de cookies solamente a travs de
conexiones seguras (por ejemplo, con $_SERVER["HTTPS"]).
httponly
Cuando es TRUE la cookie ser accesible slo a travs del protocolo HTTP. Esto significa que la
cookie no ser accesible por lenguajes de scripting, como JavaScript. Se ha indicado que esta
configuracin ayuda efectivamente a reducir el robo de identidad a travs de ataques XSS (aunque no
es soportada por todos los navegadores), pero esa afirmacin no se comparte a menudo. Agregado en
PHP 5.2.0. puede ser TRUE o FALSE.
Si existe algn tipo de salida anterior a la llamada de esta funcin, setcookie() fallar y retornar FALSE.
Si se ejecuta satisfactoriamente, retornar TRUE. Esto no indica si es que el usuario ha aceptado la cookie o no.
Si se define una cookie como:
setcookie('micookie', 'valor');

Cuando el usuario visite la siguiente pgina del sitio, o vuelva a cargar la pgina actual, se podr acceder
a la cookie a travs de $_COOKIE['micookie'] o de $HTTP_COOKIE_VARS["micookie"] o, si se ha activado
register_globals directamente como $micookie.
Se puede eliminar una cookie si se llama a la funcin setcookie() de nuevo con el mismo nombre de
cookie y una fecha de caducidad pasada. Tambin se puede definir manualmente una cookie con ayuda de la
funcin header(), que es usada para enviar encabezados HTTP sin formato, y la sintaxis de cookie que se mostr
anteriormente. Es preciso enviar los encabezados de cookie antes que ningn otro encabezado o no funcionarn,
esto es una limitacin de las propias cookie ms que una limitacin del propio lenguaje PHP. La sintaxis de
funcin header() es la siguiente:
void header ( string $string [, bool $replace = true [, int $http_response_code ]] )

Los parmetros de esta funcin son los siguientes:


string
El encabezado en formato cadena. Existen dos casos especiales en el uso de header. El primero el
encabezado que empieza con la cadena "HTTP/" (las maysculas no son importantes), es utilizado
para averiguar el cdigo de status HTTP a enviar. Por ejemplo, si se tiene Apache configurado para
usar un script en PHP para controlar las peticiones a ficheros no encontrados (usando la directiva
ErrorDocument), querr asegurarse de que el script genera el cdigo de status que corresponde.
<?php

IES Virrey Morcillo. Departamento de Informtica y Comunicaciones.

Desarrollo Web en Entorno Servidor.

UT6.- Desarrollo de aplicaciones Web utilizando cdigo embebido.

header("HTTP/1.0 404 Not Found");


?>

Para el uso de FastCGI debe usarse la siguiente respuesta para un 404:


<?php
header("Status: 404 Not Found");
?>

El segundo caso especial es el encabezado "Location:" No solamente enva el encabezado al


navegador, sino que tambin devuelve el cdigo de status (302) REDIRECT al navegador a no ser que
el cdigo de status 201 o 3xx ya haya sido enviado.
<?php
header("Location: http://www.example.com/"); /* Redireccin del navegador */
/* Asegurndonos de que el cdigo interior no ser ejecutado cuando se realiza la
redireccin. */
exit;
?>

replace
El parmetro opcional replace indica cuando el encabezado debe reemplazar un encabezado previo
similar o aadir un segundo encabezado del mismo tipo. Por defecto lo reemplazar, pero si se pasa
FALSE como segundo argumento se puede forzar mltiples encabezados del mismo tipo. Por ejemplo:
<?php
header('WWW-Authenticate: Negotiate');
header('WWW-Authenticate: NTLM', false);
?>

http_response_code
Fuerza el cdigo de respuesta HTTP a un valor especfico. Observa que este parmetro solamente
tiene efecto si string no est vaco.
La funcin no devuelve ningn valor.
Hay que tener en cuenta que header() debe ser llamada antes de mostrar nada por pantalla, etiquetas
HTML, lneas en blanco desde un fichero o desde PHP. Es un error muy comn leer cdigo con funciones como
include() o require(), u otro tipo de funciones de acceso de ficheros que incluyen espacios o lneas en blanco que
se muestran antes de llamar a la funcin header(). Sucede el mismo problema cuando se utiliza un solo fichero
PHP/HTML. Por ejemplo:
<?php
/* Esto producir un error. Fjate en el html
que se muestra antes que la llamada a header() */
header('Location: http://www.example.com/');
?>

3.2. Ejemplo de uso de cookies


Ejemplo de uso de cookies en PHP para almacenar la hoja de estilos CSS que queremos utilizar para
definir el aspecto de la pgina:
<?php
// Veo si recibo datos del formulario
if(isset($_POST["estilo"])){

IES Virrey Morcillo. Departamento de Informtica y Comunicaciones.

Desarrollo Web en Entorno Servidor.

UT6.- Desarrollo de aplicaciones Web utilizando cdigo embebido.

// Es que estoy recibiendo un estilo nuevo, lo tengo que meter en las cookies
$estilo = $_POST["estilo"];
// Meto el estilo en una cookie
setcookie("estilo", $estilo, time() + (60 * 60 * 24 * 90));
}
else {
// Si no he recibido el estilo que desea el usuario en la pgina,
// miro si hay una cookie creada
if (isset($_COOKIE["estilo"])){
// Es que tengo la cookie
$estilo = $_COOKIE["estilo"];
}
}
?>
<html>
<head>
<title>Cookies en PHP</title>
<?php
// Miro si he tengo un estilo definido, porque entonces tengo que cargar la
// correspondiente hoja de estilos
if (isset($estilo)){
echo '<link rel="STYLESHEET" type="text/css" href="' . $estilo . '.css">';
}
?>
</head>
<body>
Ejemplo de uso de cookies en PHP para almacenar la hoja de estilos CSS
que queremos utilizar para definir el aspecto de la pgina.
<form action="cookies-php.php" method="post">
Aqu puedes seleccionar el estilo que prefieres en la pgina:
<br>
<select name="estilo">
<option value="verde">Verde
<option value="rosa">Rosa
<option value="negro">Negro
</select>
<input type="submit" value="Actualizar el estilo">
</form>
</body>
</html>

IES Virrey Morcillo. Departamento de Informtica y Comunicaciones.

Desarrollo Web en Entorno Servidor.

UT6.- Desarrollo de aplicaciones Web utilizando cdigo embebido.

4. Seguimiento de sesin de un cliente web


Los lenguajes del lado del servidor proporcionan la infraestructura de informacin del estado de una
solicitud a otra (carritos de la compra, desplazamiento de datos, etc.) que necesitan las aplicaciones Web, con
una funcionalidad integrada de estado de sesin que permite realizar las siguientes acciones:

Identificar y clasificar automticamente solicitudes provenientes de un solo cliente explorador en una


sesin lgica de aplicacin en el servidor.
Almacenar datos del mbito de una sesin en el servidor para utilizarlos en diversas solicitudes de
explorador.
Provocar eventos adecuados de administracin del tiempo de vida de la sesin que se pueden controlar
con cdigo de aplicacin.
Liberar automticamente datos de las sesiones si el explorador no vuelve a visitar una aplicacin dentro
del perodo de espera que se haya especificado.

El estado de sesin permite almacenar y recuperar los valores de un usuario cuando el usuario explora
diferentes pginas que conforman una aplicacin Web. HTTP es un protocolo sin estado, lo que significa que el
servidor Web trata cada solicitud HTTP de una pgina como una solicitud independiente; el servidor no retiene
informacin alguna sobre los valores de las variables que se utilizan durante las solicitudes anteriores. El estado
de sesin identifica las solicitudes recibidas desde el mismo explorador durante un perodo limitado de tiempo
como una sesin y proporciona la capacidad de conservar los valores de las variables durante la duracin de esa
sesin.
HTTP es un protocolo sin estado, es decir, que no indica automticamente si una secuencia de solicitudes
proviene del mismo cliente ni si una sola instancia de explorador sigue viendo activamente una pgina o un sitio.
En consecuencia, la creacin de aplicaciones Web que necesitan mantener informacin del estado de una
solicitud a otra puede resultar sumamente complicada sin la ayuda adicional de una infraestructura.
El estado de sesin, sin embargo, no se conserva entre los lmites de las aplicaciones Web. Si se pasa de
una aplicacin Web a otra durante una ejecucin, la informacin de sesin no est disponible en la nueva
aplicacin.

4.1. Funcionalidad de sesin bsica


Las sesiones son una forma sencilla de almacenar datos para usuarios de manera individual usando un
ID de sesin nico. Esto se puede usar para hacer persistente la informacin de estado entre peticiones de
pginas. Los ID de sesiones normalmente son enviados al navegador mediante cookies de sesin, y el ID se usa
para recuperar los datos de sesin existente. La ausencia de un ID o una cookie de sesin permite saber a PHP
para crear una nueva sesin y generar un nuevo ID de sesin.
Los pasos bsicos de la utilizacin de sesiones son los siguientes:
1)
2)
3)
4)

Iniciar una sesin.


Registrar variables de sesin.
Utilizar variables de sesin.
Anular las variables registradas y eliminar la sesin.

Las sesiones siguen un flujo de trabajo sencillo. Cuando una sesin se inicia, PHP recuperar una sesin
existente usando el ID pasado (normalmente desde una cookie de sesin) o, si no se pasa una sesin, se crear
una sesin nueva. PHP rellenar la variable superglobal $_SESSION con cualesquiera datos de sesin de que se
inicie la sesin. Cuando PHP se cierra, automticamente toma el contenido de la variable superglobal $_SESSION,
la serializa, y la enva para almacenarla usando el gestor de almacenamiento de sesiones.
Por omisin, PHP usa el gestor interno de almacenamiento files, el cual se establece mediante
session.save_handler. ste guarda los datos de sesin en el servidor en la ubicacin especificada por la directiva
de configuracin session.save_path.

IES Virrey Morcillo. Departamento de Informtica y Comunicaciones.

Desarrollo Web en Entorno Servidor.

UT6.- Desarrollo de aplicaciones Web utilizando cdigo embebido.

Las sesiones se puede iniciar manualmente usando la funcin session_start(), y si la directiva


session.auto_start se establece a 1, una sesin se iniciar automticamente en el momento en que PHP enve
cualquier salida al buffer de salida.
Las sesiones normalmente se cierran automticamente cuando PHP termina de ejecutar un script, pero
se pueden cerrar manualmente usando la funcin session_write_close().

4.2. Uso de cookies con sesiones


Las cookies tienen algunos problemas asociados como por ejemplo que algunos navegadores no las
aceptan o que algunos usuarios pueden desactivarlas en sus navegadores. Esta es una de las razones por las que
las sesiones PHP utilizan un mtodo cookie/URL dual. Al utilizar sesiones PHP, no se tendrn que definir las
cookies manualmente. Las funciones de sesin se encargan de ello.
Se puede utilizar la funcin session_get_cookie_params() para ver los contenidos de una cookie definida
por el control de sesin. Devuelve una matriz asociativa que contiene los elementos lifetime, path y domain.
Tambin se puede utilizar:
session_set_cookie_params($lifetime $path, $domain [, $secure]);

Para definir los parmetros de la cookie de sesin.

4.3. Almacenamiento del identificador de sesin


De forma predeterminada, PHP utiliza cookies con sesiones. Si existe la posibilidad, se definir una
cookie para almacenar el identificador de sesin.
El otro mtodo que se puede utilizar consiste en aadir el identificador de sesin al URL. Es posible
indicar que se realice automticamente si se configura la directiva session.use_trans_sid en el archivo php.ini, que
de forma predeterminada est desactivada.
Tambin se puede incrustar manualmente el identificador de sesin en los enlaces para que se pase de
esta forma. El identificador de sesin se almacena en la constate SID. Para pasarlo manualmente, se debe aadir
al final de un enlace similar a un parmetro GET:
<A HREF="link.php?<?php echo strip_tags(SID); ?>">

En este caso se utiliza la funcin strip_tags() para evitar ataques de secuencias de comandos entre sitios
web.
Normalmente resulta ms sencillo compilar con --enable-trans-sid, siempre que sea posible.

4.4. Inicio de sesin


Antes de poder utilizar la funcionalidad de las sesiones, es necesario iniciar una sesin. Existen dos
formas de hacerlo:
a) La primera y ms sencilla consiste en iniciar una secuencia de comandos con una llamada a la funcin
session_start(), es decir:
session_start();

Esta funcin comprueba si ya hay un identificador de sesin actual, En caso contrario, crear uno para
tal fin. Si ya existe el identificador de sesin, bsicamente carga las variables de sesin registradas
para que se puedan utilizar. Es aconsejable llamar a la funcin session_start() al inicio de todas las
secuencias de comandos que utilicen sesiones.
b) La segunda forma de iniciar una sesin consiste en configurar PHP para que lo haga automticamente
cuando alguien visite el sitio web. Esto se puede hacer por medio de la opcin session.auto_start
incluida en el archivo php.ini.
Este mtodo presenta el inconveniente de que al activar auto_start no es posible utilizar objetos como
variables de sesin.

IES Virrey Morcillo. Departamento de Informtica y Comunicaciones.

10

Desarrollo Web en Entorno Servidor.

UT6.- Desarrollo de aplicaciones Web utilizando cdigo embebido.

4.5. Registro de variables de sesin


El registro de variables de sesin ha cambiado ltimamente en PHP. En PHP 4, las variables de sesin se
almacenaban en la matriz superglobal $_SESSION y tambin en la antigua $HTTP_SESSION_VARS. Se recomienda
que se utilice $_SESSION. Para poder crear una variable de sesin, basta con definir un elemento en esta matriz,
como se indica a continuacin:
$_SESSION['miVariable'] = 5;

Se realizar el seguimiento de la variable que se acaba de crear hasta que finalice la sesin o hasta que la
anule manualmente.

4.6. Uso de variables de sesin


Para poder introducir una variable de sesin en mbito y utilizarla, primero se debe iniciar una sesin
por medio de la funcin session_start(). Tras ello se podr acceder a la variable a travs de la matriz superglobal
$_SESSION, como por ejemplo $_SESSION['miVariable'].
Si se utiliza un objeto como variable de sesin, se debe incluir la definicin de clase antes de invocar a la
funcin session_start() para volver a cargar las variables de sesin. De esta forma PHP sabe cmo reconstruir el
objeto de sesin.
Si se ha activado register_globlas, se podr acceder a las variables de sesin utilizando sus nombres
cortos, como por ejemplo $miVariable, aunque no es una prctica recomendable.
Por otra parte, se tendr que prestar especial atencin cuando se compruebe si se han configurado las
variables de sesin, por ejemplo a travs de isset() o empty(). Se debe recordar que las variables de sesin las
puede configurar el usuario a travs de GET o POST. Se puede comprobar una variable para ver si se trata de una
variable de sesin registrada por medio de $_SESSION. Por ejemplo, se podra tener:
if (isset($_SESSION['miVariable'])) ...

4.7. Anulacin del registro de variables y eliminar la sesin


Cuando se haya terminado con una variable de sesin, se puede anular su registro. Para ello, se puede
hacer directamente si se anula el registro del correspondiente elemento de la matriz $_SESSION, como se indica a
continuacin:
unset($_SESSION['miVariable']);

Se ha de tener en cuenta que el uso de session_unregister() y session_unset() ya no es necesario ni


recomendable. Estas funciones se han quedado obsoletas.
No se debe intentar anular la matriz $_SESSION completamente, ya que si se hace se podran deshabilitar
las sesiones. Para anular el registro de todas las variables se debe utilizar:
$_SESSION = array();

Cuando se haya terminado con la sesin, primero se debera anular el registro de todas las variables y,
tras ello, llamar a la funcin session_destroy() para borrar el identificador de sesin.

4.8. Ejemplo de uso de variables de sesin


Ejemplo de cdigo para definir una variable de sesin:
<?php
session_start();
?>
<html>
<head>
<title>Generar variable de sesin</title>
</head>

IES Virrey Morcillo. Departamento de Informtica y Comunicaciones.

11

Desarrollo Web en Entorno Servidor.

UT6.- Desarrollo de aplicaciones Web utilizando cdigo embebido.

<body>
<?php
$_SESSION["miVariableSesion "] = "Hola este es el valor de la variable de sesin";
?>
</body>
</html>

Como se puede ver, es importante inicializar la sesin antes de hacer otra cosa en la pgina. Luego
podremos definir variables de sesin en cualquier lugar del cdigo PHP de la pgina.
Para leer una variable de sesin se hace a travs del mismo array asociativo $_SESSION. Es tan sencillo
como haramos para utilizar cualquier otra variable, lo nico es que tenemos que haber inicializado la sesin
previamente. Y por supuesto, que la variable que deseamos acceder exista previamente.
<?php
session_start();
?>
<html>
<head>
<title>Leo variable de sesin</title>
</head>
<body>
Muestro esa variable:
<?php
echo $_SESSION["miVariableSesion"];
?>
</body>
</html>

Como se puede ver, al inicio del cdigo hemos inicializado la sesin y luego en cualquier parte del cdigo
podramos acceder a las variables de sesin que tuvisemos creadas.
Un ejemplo clsico de utilizacin de una sesin es un contador. Este contador deber aumentar de una
unidad cada vez que recargamos la pgina o abramos el enlace:
<?php
session_start();
if (!isset($_SESSION["cuenta_paginas"])){
$_SESSION["cuenta_paginas"] = 1;
}
else{
$_SESSION["cuenta_paginas"]++;
}
?>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Contar pginas vistas por un usuario en toda su sesin</title>
</head>
<body>

IES Virrey Morcillo. Departamento de Informtica y Comunicaciones.

12

Desarrollo Web en Entorno Servidor.

UT6.- Desarrollo de aplicaciones Web utilizando cdigo embebido.

<?php
echo "Desde que entraste has visto " . $_SESSION["cuenta_paginas"] . " pginas";
?>
<br>
<br>
<a href="otracuenta.php">Ver otra vez la pgina</a>
</body>
</html>

5. Seguridad en aplicaciones Web


La seguridad combina varias disciplinas y determina a menudo si una aplicacin Web tiene xito. Una
aplicacin Web segura identifica de forma precisa a los usuarios por medio de la autenticacin, ayuda a
garantizar que esos usuarios slo tienen acceso al contenido que necesitan mediante una autorizacin,
contribuye a proteger los datos confidenciales por medio de la comunicacin y el almacenamiento cifrados, y
sigue los procedimientos de seguridad recomendados en la escritura de cdigo con el fin de evitar la
creacin de riesgos para la seguridad en la propia lgica de la aplicacin.
Si a una aplicacin Web tienen acceso usuarios desconocidos, existen muchas probabilidades de que
algn usuario malintencionado intente tambin obtener acceso. Normalmente, los servidores de Internet
accesibles al pblico se sondean a diario para descartar vulnerabilidades. Por consiguiente, se recomienda que se
tomen precauciones y adopten medidas de seguridad en todas sus aplicaciones Web.

5.1. Implementar tecnologa de seguridad


Implementar tecnologa de seguridad es slo parte de la solucin. Otra parte consiste en la vigilancia.
Aunque el sistema cuente con numerosos elementos de seguridad, es preciso vigilarlo de cerca de los modos
siguientes:
a) Supervisando los registros de eventos del sistema. Observando si se producen intentos repetidos de
iniciar sesin en su sistema o si el servidor Web recibe un nmero excesivo de solicitudes.
b) Manteniendo continuamente actualizado el servidor de la aplicacin con las ltimas revisiones de
seguridad del Sistema Operativo y de los Servidores Web, as como cualquier revisin del Sistema
Gestor de Bases de Datos o de otros orgenes de datos que pueda utilizar su aplicacin.

5.2. Modelo de amenazas


Una fase importante en el proceso de programacin de aplicaciones ms seguras consiste en ser capaz
de anticipar las amenazas que se puede sufrir. Por ejemplo, Microsoft ha elaborado el siguiente sistema de
clasificacin de las amenazas en distintas categoras:
a.

b.

Suplantacin:
Suplantar es utilizar los datos de identificacin de otro usuario o proceso de forma no autorizada. En su
versin ms simple, la suplantacin consistira en especificar las credenciales de un usuario diferente.
Un usuario malintencionado podra tambin cambiar el contenido de una cookie para fingir que es otra
persona o que la cookie proviene de un servidor diferente.
En general, es posible contribuir a evitar la suplantacin mediante una autenticacin estricta. Siempre
que alguien solicita acceso a informacin privada, es preciso asegurarse de que es quien dice ser.
Tambin se puede contribuir a la defensa contra la suplantacin manteniendo la informacin de
credenciales a salvo. Por ejemplo, no se debe guardar nunca una contrasea ni otro tipo de datos
confidenciales o privados en una cookie, donde un usuario malintencionado podra encontrarlos y
modificarlos fcilmente.
Manipulacin:
Manipular significa cambiar o eliminar un recurso sin autorizacin. El ejemplo tpico consiste en
desfigurar una pgina Web, para lo cual, el usuario malintencionado logra acceso al sitio y cambia

IES Virrey Morcillo. Departamento de Informtica y Comunicaciones.

13

Desarrollo Web en Entorno Servidor.

c.

d.

e.

f.

UT6.- Desarrollo de aplicaciones Web utilizando cdigo embebido.

algunos archivos. Un modo indirecto de manipulacin son los ataques mediante secuencias de
comandos. en los que el usuario malintencionado consigue que se ejecute cdigo (secuencia de
comandos) enmascarndolo como la entrada de datos de un usuario en un formulario o como un
vnculo.
Una defensa fundamental contra la manipulacin consiste en usar la seguridad del Sistema Operativo
para bloquear los archivos, directorios y otros recursos de mismo. La aplicacin tambin debera
ejecutarse con privilegios mnimos. Para ayudar a evitar los ataques mediante secuencias de comandos,
no se debe confiar de la informacin que proceda de un usuario, ni de una base de datos. Siempre que se
obtenga informacin de una fuente que no sea de confianza, hay que procesarla y asegrese de que no
contiene cdigo ejecutable.
Repudio:
Una amenaza de repudio implica llevar a cabo una transaccin de manera que no haya pruebas
fehacientes de los actores principales de la transaccin. En una aplicacin Web, esto puede significar que
se est suplantando a un usuario inocente usando sus credenciales. Contribuir a la proteccin contra el
repudio es posible, de nuevo, aplicando una autenticacin estricta. Adems, se deben usar las funciones
de inicio de sesin del Sistema Operativo para mantener un registro de auditora de cualquier actividad
en el servidor.
Revelacin de informacin:
Revelacin de informacin significa simplemente robar o desvelar informacin que se supone que es
confidencial. Un ejemplo clsico es robar contraseas, pero puede implicar el acceso a cualquier archivo
o recurso del servidor.
La mejor proteccin contra la revelacin de informacin es no tener informacin que revelar. Por
ejemplo, si se evita el almacenamiento de contraseas, ningn usuario malintencionado podr robarlas.
Una alternativa al almacenamiento de las contraseas consiste en guardar slo un valor hash de stas.
De este modo, cuando un usuario presenta sus credenciales, se puede extraer el valor hash de su
contrasea y compararlo con el almacenado.
Si, an as, se almacena informacin confidencial, se debe utilizar la seguridad del propio sistema para
ayudar a protegerla. Como en todos los casos anteriores, se debera utilizar la autenticacin para
contribuir a garantizar que slo los usuarios autorizados pueden tener acceso a la informacin
restringida. Si se tiene que exponer informacin confidencial, es recomendable que se cifre cuando se
almacene y que se utilice SSL (Secure Sockets Layer) para cifrar la informacin cuando se enve al
explorador o se reciba de ste.
Denegacin de servicio:
Un ataque de denegacin de servicio consiste en hacer deliberadamente que una aplicacin est menos
disponible de lo que debera. Un ejemplo tpico es sobrecargar una aplicacin Web de forma que no
pueda servir a los usuarios normales. Como alternativa, los usuarios malintencionados pueden intentar
simplemente bloquear el servidor.
Los Servidores Web permiten limitar las aplicaciones de forma que slo sirvan un nmero determinado
de solicitudes, lo que podra resultar til para negar el acceso a usuarios o direcciones IP que se sabe que
son malintencionados. Para mantener las aplicaciones en lnea, es esencial ejecutar cdigo slido. Se
debe probar exhaustivamente la aplicacin y responder apropiadamente a los errores siempre que sea
posible.
Concesin de privilegio:
Un ataque de concesin de privilegio consiste en usar medios malintencionados para obtener ms
permisos de los asignados normalmente. Por ejemplo, en un ataque de concesin de privilegio que tenga
xito, un usuario malintencionado consigue obtener privilegios administrativos para el Servidor Web, lo
que le proporciona acceso a todos los datos del servidor, as como el control de las funciones de ste.

5.3. Recomendaciones de seguridad para aplicaciones Web


Incluso los mtodos de seguridad de aplicaciones ms elaborados pueden verse comprometidos si un
usuario malintencionado logra obtener acceso a los equipos usando medios simples. Entre las recomendaciones
generales de seguridad para aplicaciones Web se encuentran:

IES Virrey Morcillo. Departamento de Informtica y Comunicaciones.

14

Desarrollo Web en Entorno Servidor.

UT6.- Desarrollo de aplicaciones Web utilizando cdigo embebido.

Realizar copias de seguridad de los datos con asiduidad y guardarlos en un lugar seguro.
Mantener el servidor Web en un lugar fsico seguro, de forma que los usuarios no autorizados no puedan
tener acceso a l, apagarlo, llevrselo, etc.
Utilizar el sistema de archivos apropiado, por ejemplo NTFS, Ext4, etc.
Proteger el servidor Web y todos los equipos de la misma red con contraseas seguras.
Seguir los procedimientos recomendados para asegurar los servicios Web.
Cerrar los puertos que no se utilicen y desactivar los servicios que no se estn en uso.
Ejecutar un programa antivirus que supervise el trfico.
Usar un firewall.
Mantenerse informado sobre las actualizaciones de seguridad ms recientes del Sistema Operativo y
otros fabricantes, e instalarlas.
Usar las funciones de registro de eventos del sistema y examinar los registros con frecuencia para
detectar actividades sospechosas. Esto incluye los intentos repetidos de iniciar sesin en el sistema y un
exceso de solicitudes en el servidor Web.
Ejecutar las aplicaciones con el mnimo de privilegios.
Conocer a los usuarios.
Protegerse contra entradas malintencionadas.
Tener acceso seguro a bases de datos.
Crear mensajes de error seguros.
Mantener segura la informacin confidencial.
Usar cookies de forma segura.
Protegerse contra amenazas de denegacin de servicio.

IES Virrey Morcillo. Departamento de Informtica y Comunicaciones.

15

Anda mungkin juga menyukai